专注Java教育14年 全国咨询/投诉热线:444-1124-454
星辉LOGO图
始于2009,口口相传的Java黄埔军校
首页 hot资讯 两个多线程框架的实现方法

两个多线程框架的实现方法

更新时间:2021-06-23 12:09:02 来源:星辉 浏览762次

Java编写程序都运行在在Java虚拟机(JVM)中,在JVM的内部,程序的多任务是通过线程来实现的。每用Java命令启动一个Java应用程序,就会启动一个JVM进程。在同一个JVM进程中,有且只有一个进程,就是它自己。在这个JVM环境中,所有程序代码的运行都是以线程来运行。

在Java中,多线程的实现有两种基本方式:继承java.lang.Thread类;实现java.lang.Runnable接口。(优先选择)。

第三种方式(少):使用ExecutorService、Callable、Future实现有返回结果的多线程。

1.继承Thread类来实现多线程

当一个类继承Thread类时,在类中必须重载run()方法,同时这个run()方法也是线程的入口,在调用的过程中,通过调用start()方法来启动新线程,其基本框架为:

class 类名 extends Thread{
方法1;
方法2;
…
  public void run(){
   // other code…
  }
 属性1;
 属性2;
  …  
}

一般生活场窗口售票情况:

class TestThread extends Thread
 {
    private String name;
    public TestThread(String name)
     {
        this.name=name;
    }
     public void run()
    {
         for (int i = 0; i < 7; i++)
        {
            if (num > 0)
            {
                System.out.println(name+"正在卖票  "+"num= " + num--);
             }
        }
     }
    public static void main(String[] args)
    {
        TestThread h1 = new TestThread("窗口1");
        TestThread h2 = new TestThread("窗口2");
        TestThread h3 = new TestThread("窗口3");
       h1.start();
       h2.start();
       h3.start();
     }
    private int num = 4;
 }

这样出现的问题是:1.不清楚线程之间执行的具体顺序,2.相当于每个窗口都在售卖4张票。

优化方案:实现Runnable接口

2.实现Runnable接口来实现多线程

和继承Thread类似,当一个类实现Runnable接口时,在类中也必须重载run()方法,同时这个run()方法也是线程的入口,在调用的过程中,通过调用start()方法来启动新线程,其基本框架为:

class 类名 implements Runnable{
 方法1;
 方法2;
 …
 public void run(){
  // other code…
  }
属性1;
属性2;
… 
}

代码改进:

class MyThread implements Runnable
{ 
    private int ticket = 5;  //5张票 
    public void run() 
    {
         for (int i=0; i<=20; i++) 
         {
            if (this.ticket > 0) 
             {
                 System.out.println(Thread.currentThread().getName()+ "正在卖票"+this.ticket--);
            }
         }
     }
 }
 public class TestThread {     
     public static void main(String [] args) 
     {
        MyThread my = new MyThread();
        new Thread(my, "1号窗口").start();
        new Thread(my, "2号窗口").start();
        new Thread(my, "3号窗口").start();
     }
 }

程序执行的结果为:

1 1号窗口正在卖票5

2 1号窗口正在卖票4

3 1号窗口正在卖票3

4 2号窗口正在卖票2

5 1号窗口正在卖票1

3.使用ExecutorService、Callable、Future实现有返回结果的多线程

ExecutorService、Callable、Future这个对象实际上都是属于Executor框架中的功能类。返回结果的线程是在JDK1.5中引入的新特征,确实很实用,有了这种特征我就不需要再为了得到返回值而大费周折了,而且即便实现了也可能漏洞百出。可返回值的任务必须实现Callable接口,类似的,无返回值的任务必须Runnable接口。

import java.util.concurrent.*;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
/**
* 有返回值的线程
*/
@SuppressWarnings("unchecked")
public class Test {
public static void main(String[] args) throws ExecutionException,
    InterruptedException {
   System.out.println("----程序开始运行----");
   Date date1 = new Date();
   int taskSize = 5;
   // 创建一个线程池
   ExecutorService pool = Executors.newFixedThreadPool(taskSize);
   // 创建多个有返回值的任务
   List<Future> list = new ArrayList<Future>();
   for (int i = 0; i < taskSize; i++) {
    Callable c = new MyCallable(i + " ");
    // 执行任务并获取Future对象
    Future f = pool.submit(c);
    // System.out.println(">>>" + f.get().toString());
    list.add(f);
   }
   // 关闭线程池
   pool.shutdown();
   // 获取所有并发任务的运行结果
   for (Future f : list) {
    // 从Future对象上获取任务的返回值,并输出到控制台
    System.out.println(">>>" + f.get().toString());
   }
   Date date2 = new Date();
   System.out.println("----程序结束运行----,程序运行时间【"
     + (date2.getTime() - date1.getTime()) + "毫秒】");
}
}
class MyCallable implements Callable<Object> {
private String taskNum;
MyCallable(String taskNum) {
   this.taskNum = taskNum;
}
public Object call() throws Exception {
   System.out.println(">>>" + taskNum + "任务启动");
   Date dateTmp1 = new Date();
   Thread.sleep(1000);
   Date dateTmp2 = new Date();
   long time = dateTmp2.getTime() - dateTmp1.getTime();
   System.out.println(">>>" + taskNum + "任务终止");
   return taskNum + "任务返回运行结果,当前任务时间【" + time + "毫秒】";
}
}

代码说明:

上述代码中Executors类,提供了一系列工厂方法用于创先线程池,返回的线程池都实现了ExecutorService接口。

public static ExecutorService newFixedThreadPool(int nThreads)

创建固定数目线程的线程池。

public static ExecutorService newCachedThreadPool()

创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。

public static ExecutorService newSingleThreadExecutor()

创建一个单线程化的Executor。

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)

创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。

ExecutoreService提供了submit()方法,传递一个Callable,或Runnable,返回Future。如果Executor后台线程池还没有完成Callable的计算,这调用返回Future对象的get()方法,会阻塞直到计算完成。

以上就是星辉小编介绍的"两个多线程框架的实现方法",希望对大家有帮助,想学习多线程的小伙伴可以观看Java多线程视频教程进行学习,如有疑问,请在线咨询,有专业老师随时为您服务。

提交申请后,顾问老师会电话与您沟通安排学习

免费课程推荐 >>
技术文档推荐 >>