少年游

欲买桂花同载酒,终不似,少年游。

0%

Java多线程

继承Thread

缺点:继承只能继承一次。扩展性不强
重写run方法,来自定义线程执行任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyThread extends Thread{

@Override
public void run() {
System.out.println("MyThread.run()");
}

public static void main(String[] args){
MyThread thread1 = new MyThread();
MyThread thread2 = new MyThread();
thread1.start();
thread2.start();
}
}

实现Runnable接口

优点:可扩展性强
方法:通过实现接口,然后Thread构造方法传参新建thread2类,start()启动。

1
2
3
4
5
6
7
8
9
10
11
12
13
public class MyThread2 implements Runnable{

@Override
public void run() {
System.out.print("MyThread2.run()");
}

public static void main(String[] args){
MyThread2 thread = new MyThread2();
Thread thread2 = new Thread(thread);
thread2.start();
}
}

Thread类本身实现了Runable接口,而且除了默认构造,还有一个带参构造,传入target

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//Thread源代码
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}

public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}

public void run() {
if (target != null) {
target.run();
}
}

ExecutorService、Callable、Future带返回结果的线程实现

Callable:执行任务并返回结果。
Future:Future接口是Java线程Future模式的实现,可以来进行异步计算。

Future模式:我有一个任务,提交给了Future,Future替我完成这个任务。期间我自己可以去做任何想做的事情。一段时间之后,我就便可以从Future那儿取出结果。就相当于下了一张订货单,一段时间后可以拿着提订单来提货,这期间可以干别的任何事情。其中Future 接口就是订货单,真正处理订单的是Executor类,它根据Future接口的要求来生产产品。

ExecutorService:继承自Executor,线程池操作类,创建,执行,关闭

核心
  • Future f = pool.submit(c);
  • Void f = pool.execute(RunnableImplements);
  • 1
    2
    3
    4
    5
    6
    7
    //ExecutorService部分源码 

    <T> Future<T> submit(Callable<T> task);

    <T> Future<T> submit(Runnable task, T result);

    Future<?> submit(Runnable task);
    1
    2
    3
    4
    5
    另外 
    //Executor源码
    public interface Executor {
    void execute(Runnable command);
    }
    小例子
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    /**
    * 有返回值的线程
    */
    public class MyThread3 {
    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<Object>> list = new ArrayList<Future<Object>>();
    for (int i = 0; i < taskSize; i++) {
    Callable<Object> c = new MyCallable(i + " ");
    // 执行任务并获取Future对象
    Future<Object> f = pool.submit(c);
    // System.out.println(">>>" + f.get().toString());
    list.add(f);
    }
    // 关闭线程池
    pool.shutdown();

    // 获取所有并发任务的运行结果
    for (Future<Object> 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 + "毫秒】";
    }
    }

    如有不懂,可以多翻阅源代码。

    Reference

    JAVA多线程实现的三种方式
    java Future 接口介绍
    线程池中execute和submit的区别
    EXECUTORSERVICE线程池讲解