java多线程的3种实现方式

多线程相关的问题

1.什么是进程?

​ 正在执行的程序

2.什么是线程?

​ 进程的子单位,一个能够完成独立功能的执行路径

3.为什么需要开启多线程?

  • 当执行某些耗时操作的任务的时候需要开启多线程,防止线程阻塞
  • 能够让两个任务看起来像是在同时执行
  • 提高CPU的使用率,进而提高进程和内存的使用率

4.为什么开启多线程会同时执行?

​ 因为CPU切换执行的速度太快了,肉眼无法差距

5.开启多线程是不是越多越好,提高了效率还是降低了效率?

​ 不是,线程越多,效率越慢,但是太少,浪费CPU资源,所以,合理利用CPU

6.并发和并行的区别

  • 并发 --> 在同一个时间段下同时执行多个线程,看起来像同时执行
  • 并行 --> 在同一个时间刻度下(不能够在分割的时间单位)执行多个线程,本质就上就是同时执行

CPU在某一个最小的时间刻度单位下,执行的是一个进程的一个线程的一个不可再分割的原子性语句

线程开启方式

Java提供了三种创建线程方法:

​ 1.继承Thread类的方式

​ 2.实现Runnable的方式

​ 3.通过 Callable 和 Future 创建线程。

方式一:继承Thread类

​ 1.自定义类MyThread继承Thread类。3 ​ 2.MyThread类里面重写run()方法。 ​ 3.创建线程对象。 ​ 4.启动线程。 注意: ​ 1、启动线程使用的是start()方法而不是run()方法 ​ 2、线程能不能多次启动

线程对象调用 run方法和调用start方法区别?

  • 线程对象调用run方法不开启线程。仅是对象调用方法。
  • 线程对象调用start开启线程,并让jvm调用run方法在开启的线程中执行

代码演示使用方式一开启线程

1// 方式二:实现Runnable接口 2class CalculateRunnable implements Runnable { 3 private int m; 4 private int n; 5 public CalculateRunnable(int m, int n) { 6 super(); 7 this.m = m; 8 this.n = n; 9 } 10 public CalculateRunnable() { 11 super(); 12 } 13 @Override 14 public void run() { 15 int sum = 0; 16 for (int i = m; i <= n; i++) { 17 sum += i; 18 System.out.println("CalculateRunnable子线程: " + i); 19 } 20 System.out.println(m + "~" + n + "的和: " + sum); 21 } 22}

方式二:实现Runnable接口

​ 1.自定义类MyRunnable实现Runnable接口 ​ 2.重写run()方法 ​ 3.创建MyRunnable类的对象 ​ 4.创建Thread类的对象,并把步骤3创建的对象作为构造参数传递 ​ 5.启动线程

实现接口方式的好处 可以避免由于Java单继承带来的局限性。 适合多个相同程序的代码去处理同一个资源的情况,把线程同程序的代码,数据有效分离,较好的体现了面向对象的设计思想。

代码演示方式二开启线程

1// 方式一:继承Thread类 2class CopyThread extends Thread { 3 private File srcFile; 4 private File descFile; 5 6 public CopyThread() { 7 super(); 8 } 9 10 public CopyThread(File srcFile, File descFile) { 11 super(); 12 this.srcFile = srcFile; 13 this.descFile = descFile; 14 } 15 16 @Override 17 public void run() { 18 // main方法怎么写,这里就怎么写 19 copy(srcFile, descFile); 20 } 21 22 public void copy(File srcFile, File descFile) { 23 try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile)); 24 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(descFile))){ 25 byte[] bys = new byte[1024]; 26 int len = 0; 27 while ((len = bis.read(bys)) != -1) { 28 bos.write(bys, 0, len); 29 bos.flush(); 30 } 31 } catch (FileNotFoundException e) { 32 e.printStackTrace(); 33 } catch (IOException e) { 34 e.printStackTrace(); 35 } 36 } 37}
主方法调用
1 public static void main(String[] args) { 2 CopyThread ct = new CopyThread(new File("Test.java"), new File("Test.txt")); 3 CalculateRunnable cr = new CalculateRunnable(1, 200); 4 Thread t = new Thread(cr); 5 ct.start(); 6 t.start(); 7 for (int i = 0; i < 100; i++) { 8 System.out.println("main线程: " + i); 9 } 10 }

方式三: Callable 和 Future 创建线程。

  • 创建 Callable 接口的实现类,并实现 call() 方法,该 call() 方法将作为线程执行体,并且有返回值。
  • 创建 Callable 实现类的实例,使用 FutureTask 类来包装 Callable 对象,该 FutureTask 对象封装了该 Callable 对象的 call() 方法的返回值。
  • 使用 FutureTask 对象作为 Thread 对象的 target 创建并启动新线程。
  • 调用 FutureTask 对象的 get() 方法来获得子线程执行结束后的返回值。

继承Thread和实现Runnable的方式的特点:

​ 1.没有返回结果

​ 2.没有异常

Callable和Runnable的区别:

​ 1.Runnable无返回值,没有异常抛出的

​ 2.Callable可以在启动线程中获取返回值, 以及接受子线程的异常

线程间的数据传递:线程通信

​ A线程中开启了B线程

​ A --> B 通过构造方法

​ B --> A 通过Callable方式

1public class CallableDemo{ 2 public static void main(String[] args) { 3 FutureTask<Integer> task = new FutureTask<>(new CalculateCallable(0,100)); 4 Thread t = new Thread(task); 5 t.start(); 6 7 try { 8 Integer i = task.get(); 9 System.out.println("计算结果: " + i); 10 } catch (InterruptedException | ExecutionException e) { 11 e.printStackTrace(); 12 } catch (Exception e) { 13 e.printStackTrace(); 14 } 15 16 System.out.println("程序结束"); 17 } 18} 19 20 21class CalculateCallable implements Callable<Integer> { 22 23 private int m; 24 private int n; 25 26 public CalculateCallable() { 27 super(); 28 } 29 30 public CalculateCallable(int m, int n) { 31 super(); 32 this.m = m; 33 this.n = n; 34 } 35 36 @Override 37 public Integer call() throws Exception { 38 int sum = 0; 39 for (int i = m; i <= n; i++) { 40 System.out.println("子线程: " + i); 41 sum += i; 42 throw new NullPointerException("空指针异常!"); 43 } 44 return sum; 45 } 46}
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

java多线程常见问题

Java多线程是什么Java提供的并发(同时、独立)处理多个任务的机制。多个线程共存于同一JVM进程里面,所以共用相同的内存空间,较之多进程,多线程之间的通信更轻量级。依我的理解,Java多线程完全就是为了提高CPU的利用率。Java的线程有4种状态,新建(New)、运行(Runnable)、阻塞(Blocked)、结束(Dead),关键就在于阻塞(Bl

java多线程面试题_线程并发面试题

1、什么是线程?线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速。比如,如果一个线程完成一个任务要100毫秒,那么用十个线程完成改任务只需10毫秒。2、线程和进程有什么区别?线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不

Java高级教程02

\TOC\1.Java线程1.1.多线程和多进程多进程:操作系统能够同时进行多个任务:每个app(word,播放器,浏览器)可以同时运行多线程:同一应用程序中哟多个顺序流同时执行线程是进程中的一部分1.2.线程的执行过程:!(