Java多线程的实现方式

一、继承Thread

  Thread 类本质上是实现了 Runnable 接口的一个实例,表明一个线程的实例。启动线程的惟一方法就是经过 Thread 类的 start()实例方法。 start()方法是一个 native 方法 ,它将启动一个新线程,并执行 run()方法。

demo:

package com.bitch.demo;

public class MyThread extends Thread{

    public void run() {
        System.out.println("hello,luyizhou");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("hello,lucian");
    }

}

二、实现Runnable接口

  若是本身的类已经 extends 另外一个类,就没法直接 extends Thread,此时,能够实现一个Runnable 接口。

demo:

 1 package com.bitch.demo;
 2 
 3 public class MyThread extends HelloWorld implements Runnable{
 4 
 5     public void run() {
 6         System.out.println("hello,luyizhou");
 7         try {
 8             Thread.sleep(1000);
 9         } catch (InterruptedException e) {
10             e.printStackTrace();
11         }
12         System.out.println("hello,lucian");
13     }
14 
15 }
 1 package com.bitch.demo;
 2 
 3 public class ThreadTest {
 4 
 5     public static void main(String[] args) {
 6 
 7         System.out.println("111");
 8         MyThread myThread = new MyThread();
 9 
10         Thread thread = new Thread(myThread);
11         thread.start();
12 
13         System.out.println("222");
14     }
15 }

三、使用Callable和Future创建

上面的两种方式都有这两个问题:

  1. 无法获取子线程的返回值
  2. run方法不可以抛出异常

demo:

 1 package com.bitch.demo;
 2 
 3 import java.util.concurrent.Callable;
 4 
 5 public class MyThread extends HelloWorld implements Callable {
 6 
 7     public Object call() throws Exception {
 8         System.out.println("hello,luyizhou");
 9         try {
10             Thread.sleep(1000);
11         } catch (InterruptedException e) {
12             e.printStackTrace();
13         }
14         System.out.println("hello,lucian");
15         return null;
16     }
17 }
 1 package com.bitch.demo;
 2 
 3 import java.util.concurrent.FutureTask;
 4 
 5 public class ThreadTest {
 6 
 7     public static void main(String[] args) {
 8 
 9         System.out.println("111");
10         MyThread myThread = new MyThread();
11 
12         FutureTask futureTask = new FutureTask(myThread);
13         new Thread(futureTask).start();
14 
15         System.out.println("222");
16     }
17 }

四、使用线程池

线程池提供了一个线程队列,队列中保存着所有等待状态的线程,避免了创建与销毁额外开销,提高了响应的速度,建议大家使用这种方法创建、管理线程。

demo:

 1 package com.bitch.demo;
 2 
 3 import java.util.concurrent.ExecutorService;
 4 import java.util.concurrent.Executors;
 5 
 6 public class ThreadTest {
 7 
 8     public static void main(String[] args) {
 9 
10         System.out.println("111");
11         
12         ExecutorService executorService = Executors.newFixedThreadPool(10);
13         executorService.execute(() -> System.out.println("这是个新的线程" + Thread.currentThread().getName()));
14         executorService.shutdown();
15         
16         System.out.println("222");
17     }
18 }

五、对比

1 继承Thread类

  1. 实现简单,直接继承Thread即可。并且在run()方法内获取当前线程直接使用this
    就可以了,无须使用Thread.currentThread() 方法;
  2. java当中的继承只能是单继承,一个类只能继承一个直接父类。如果一个类继承了Thread类,就不能有其他的父类。
  3. 创建的对象,即封装了线程任务,又封装了线程对象的特点(线程对象),不同的东西封装到了一个对象之中,不符合java面向对象的特点。

2 实现Runnable接口

  1. run()方法内获取当前线程不能使用使用this,必须使用Thread.currentThread() 方法;
  2. 将线程任务单独的封装到一个接口实现类当中,将线程任务和线程对象进行了分离:Runnable接口实现类当中定义线程任务,Thread类封装了线程对象,将不同的功能封装到不同的对象之中,这种思想更加的符合面向对象的特点。
  3. 避免了单继承带来的局限性。
  4. 适合多条线程处理同一个资源的情况,很容易的实现资源共享。需要多个线程完成一个任务时,比如:多个线程共同卖100张票,他们需要共享100张票这个资源。

3 实现Callable接口

  具有实现Runnable接口的特点,同时还能获取返回值,并且可以抛出异常。

posted @ 2022-03-02 14:11  luyizhou  阅读(25)  评论(0编辑  收藏  举报