欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java中线程实现方式(execute和submit方式的区别)

程序员文章站 2022-04-15 17:57:56
1. Java中多线程有哪几种实现方式?继承 Thread 类并重写run方法实现Runnable接,重写run方法实现 Callable 接口,通过FutureTask包装器来创建Thread线程通过线程池创建线程1.1继承 Thread 类并重写run方法java.lang.Thread 类的实例就是一个线程但是它需要调用java.lang.Runnable接口来执行,由于线程类本身就是调用的Runnable接口所以你可以继承 java.lang.Thread 类或者直接调用Runnab...

1. Java中多线程有哪几种实现方式?

  • 继承 Thread 类并重写run方法
  • 实现Runnable接,重写run方法
  • 实现 Callable 接口,Callable的任务执行后可返回值,此时需要调用FutureTask.get()方法实现,此方法会阻塞主线程直到获取‘将来’结果;当不调用此方法时,主线程不会阻塞。
  • 通过线程池创建线程

2. 执行execute()方法和submit()方法的区别是什么呢?

  • execute()方法用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功与否;
  • submit()方法用于提交需要返回值的任务。线程池会返回一个 Future 类型的对象,通过这个 Future 对象可以判断任务是否执行成功,并且可以通过 Future 的 get()方法来获取返回值,get()方法会阻塞当前线程直到任务完成,而使用 get(long timeout,TimeUnit unit)方法则会阻塞当前线程一段时间后立即返回,这时候有可能任务没有执行完。
1.1继承 Thread 类并重写run方法

java.lang.Thread 类的实例就是一个线程但是它需要调用java.lang.Runnable接口来执行,由于线程类本身就是调用的Runnable接口所以你可以继承 java.lang.Thread 类或者直接调用Runnable接口来重写run()方法实现线程。
java中线程实现方式(execute和submit方式的区别)

/**
 * 继承 Thread 类并重写run方法
 */ public class T01CreateThread01 extends Thread { private int i; @Override public void run() { for (; i < 100; i++) { System.out.println(getName() + ":" + i + "  (run) "); } } public static void main(String[] args) { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + ":" + i + "  (main)"); if (i == 20) { new T01CreateThread01().start(); new T01CreateThread01().start(); } } } } 
  • 两个线程输出的i变量不连续,因为每次创建线程对象时都需要创建一个ThreadTest对象,所以两线程不能共享该实例变量。

  • 调用start方法后线程并没有马上执行而是进入就绪状态,等待获取CPU资源后才会真正处于运行状态。

  • 使用继承的优点:在 run() 方法内获取当前线程可直接使用 this ,无须使用 Thread.cunrrentThread() 方法。

  • 缺点:Java不支持多继承,继承Thread类后就不能继承其他类了;多个线程之间不能共享线程类的实例变量。

1.2实现Runnable接口的run方法

java中线程实现方式(execute和submit方式的区别)

/**
 *实现 Runnable 接口的 run 方法
 */ public class T01CreateThread02 implements Runnable { private int i; @Override public void run() { for (; i < 100; i++) { System.out.println(Thread.currentThread().getName() + ":" + i + "(run)"); } } public static void main(String[] args) { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + ":" + i + "(main)"); if (i == 20) { T01CreateThread02 r = new T01CreateThread02(); new Thread(r, "新线程1").start(); new Thread(r, "新线程2").start(); } } } } 
  • 优点:还可以继承其他类; 多个线程共享同一个target对象,所以适合多个相同线程来处理同一个份资源的情况,从而可以将CPU、代码和数据分开,形成清晰的模型,体现了面向对象的思想。
  • 缺点:如果需要访问当前线程,必须使用 Thread.currentThread() 的方法; 和继承方法一样没有返回值
1.3实现 Callable 接口

java中线程实现方式(execute和submit方式的区别)
java中线程实现方式(execute和submit方式的区别)
如何理解实现Callable接口的方式创建多线程比实现Runnable接口的方式更强大?

  • call可以有返回值
  • 2.call可以抛出异常,被外面的操作捕获,获取异常的信息
  • 3.Callable是支持 泛型的
/**
 * 实现 Callable 接口
 */ import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; //1.创建一个实现Callable的实现类 public class T01CreateThread04 implements Callable<Integer> { private int i; //2.实现call方法,将此线程需要执行的操作声明在call中 @Override public Integer call() throws Exception { for (; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " : " + i + "  (run)"); } return i; } public static void main(String[] args) { //3.创建Callable接口实现类的对象 T01CreateThread04 c = new T01CreateThread04(); //4.将此Callable接口实现类的对象作为传递到FutureTask构造器中,创建FutureTask对象 FutureTask<Integer> futureTest1 = new FutureTask<>(c); FutureTask<Integer> futureTest2 = new FutureTask<>(c); for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " : " + i + "  (main)"); if (i == 20) { //5.将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start() new Thread(futureTest1, " 新线程1 ").start(); new Thread(futureTest2, " 新线程2 ").start(); } } try { //6.获取Callable中call方法的返回值 //get()返回值即为FutureTask构造器参数Callable实现类重写的call()的返回值 System.out.println("线程返回值:" + futureTest2.get()); } catch (Exception e) { e.printStackTrace(); } } } 
1.4使用线程池

java中线程实现方式(execute和submit方式的区别)
java中线程实现方式(execute和submit方式的区别)
好处:

  • 1.提高响应速度(减少了创建新线程的时间)
  • 2.降低资源消耗(重复利用线程池中的线程,不需要每次都创建)
  • 3.便于线程管理
  • corePoolSize:核心池的大小
  • maximumPoolSize:最大线程数
  • keepAliveTime:县城没有任何时最多保持多长时间后会终止
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; class NumberThread1 implements Runnable{ @Override public void run() { for (int i=0;i<=100;i++){ if (i%2==0){ System.out.println(Thread.currentThread().getName() + ":" + i + "(run)"); } } } } class NumberThread2 implements Runnable{ @Override public void run() { for (int i=0;i<=100;i++){ if (i%2!=0){ System.out.println(Thread.currentThread().getName() + ":" + i + "(run)"); } } } } public class T01CreateThread05 { public static void main(String[] args) { //1.提供指定线程数量的线程池 ExecutorService service= Executors.newFixedThreadPool(10); //设置线程池的属性 System.out.println(service.getClass()); //执行指定的线程的操作。需要提供实现Runnable接口或者Callable接口的实现类的对象 service.execute(new NumberThread1());//适用于Runnable service.execute(new NumberThread2());//适用于Runnable //        service.submit(Callable callable);//适用于Callable //      关闭连接池 service.shutdown(); } } 

6.线程的常用方法有哪些?

start、run、setName、setPriority、setDaemon、join、yield、sleep、interrupt

本文地址:https://blog.csdn.net/weixin_43338519/article/details/107885931

相关标签: 并发多线程