Java多线程
2021/11/13 17:10:58
本文主要是介绍Java多线程,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
线程创建方式
- 继承Thread类:实现起来简单,而且要获取当前线程,无需调用Thread.currentThread()方法,直接使用this即可获取当前线程,线程类已经继承Thread类了,就不能再继承其他类,多个线程不能共享同一份资源(如前面分析的成员变量 i )
- 实现Runnable接口:线程类只是实现了接口,还可以继承其他类,多个线程可以使用同一个target对象,适合多个线程处理同一份资源的情况。要访问当前线程,必须调用Thread.currentThread()方法。
- 通过Callable和Future接口创建线程:上述两种方法都不能有返回值,且不能声明抛出异常。而Callable接口则实现了此两点,Callable接口如同Runable接口的升级版,其提供的call()方法将作为线程的执行体,同时允许有返回值。
Future
- get:方法可以当任务结束后返回一个结果,如果调用时,工作还没有结束,则会阻塞线程,直到任务执行完毕
- get(long timeout,TimeUnit unit):做多等待timeout的时间就会返回结果
- cancel(boolean mayInterruptIfRunning):方法可以用来停止一个任务,如果任务可以停止(通过mayInterruptIfRunning来进行判断),则可以返回true,如果任务已经完成或者已经停止,或者这个任务无法停止,则会返回false.
- isDone():方法判断当前方法是否完成
- isCancel():方法判断当前方法是否取消
Callable Future示例
public class FutureTest { public static void main(String[] args) throws ExecutionException, InterruptedException { FutureTask<String> futureTask = new FutureTask<>(new MyCallable()); new Thread(futureTask).start(); System.out.println(futureTask.get()); } } class MyCallable implements Callable<String> { @Override public String call() throws Exception { System.out.println("call"); return "MyCallable"; } }
改变线程状态
- Thread.sleep(long millis) 线程调用此方法,则进入RIMED.WAITING状态,但不释放锁,millis后线程自动苏醒进入就绪状态。作用:给其他线程执行的最佳机会。
- Thread.yield():线程调用此方法,当前线程放弃获取的CPU时间片,但不释放资源,由运行状态变为就绪状态,让OS再次选择线程。作用:让相同优先级的线程轮流执行,但并不一定会轮流执行,实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中,Thread.yield()不会阻塞线程。该方法sleep()类似,只是不能由用户指定暂停时长。
- join()/join(long millis):当前线程调用其他线程的join()方法,当前线程进入WAITING/TIMED_WAITING状态,当前线程不会释放已经持有的对象锁,线程执行完或millis时间到,当前线程进入就绪状态。
- wait:当前线程调用对象wait(),当前线程释放对象锁,进入等待队列。依靠notfiy()/notifyAll()唤醒或wait(long millis)时间到自然醒。
- notfiy:唤醒此对象监视器上等待的单个线程,选择是任意。
- notfiyAll:唤醒此对象监视器上等待的所有线程。
join 示例
public class Join { public static void main(String[] args) { Object object = new Object(); MyThread myThread = new MyThread("myThread", object); myThread.start(); synchronized (myThread) { for (int i = 0; i < 50; i++) { if (i == 20) { try { myThread.join(); } catch (Exception e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + "--" + i); } } } } class MyThread extends Thread { private String name; private Object lock; public MyThread(String name, Object object) { this.name = name; this.lock = object; } @Override public void run() { synchronized (this) { for (int i = 0; i < 20; i++) { System.out.println(name + "-" + i); } } } }
wait notifyAll 示例
public class WaitAndNotify { public static void main(String[] args) { MethodClass methodClass = new MethodClass(); Thread thread1 = new Thread(() -> { try { methodClass.product(); } catch (Exception e) { e.printStackTrace(); } }, "thread1"); Thread thread2 = new Thread(() -> { try { methodClass.customer(); } catch (Exception e) { e.printStackTrace(); } }, "thread2"); Thread thread3 = new Thread(() -> { try { methodClass.customer(); } catch (Exception e) { e.printStackTrace(); } }, "thread3"); thread1.start(); thread2.start(); thread3.start(); } } class MethodClass { final int MAX_COUNT = 20; int PRODUCT_COUNT = 0; public synchronized void product() throws Exception { while (true) { System.out.println(Thread.currentThread().getName() + "::run::" + PRODUCT_COUNT); Thread.sleep(100); if (PRODUCT_COUNT >= MAX_COUNT) { System.out.println("暂停生产"); wait(); } else { PRODUCT_COUNT++; } notifyAll(); } } public synchronized void customer() throws Exception { while (true) { System.out.println(Thread.currentThread().getName() + "::run::" + PRODUCT_COUNT); Thread.sleep(100); if (PRODUCT_COUNT <= 0) { System.out.println("暂停消费"); wait(); } else { PRODUCT_COUNT--; } notifyAll(); } } }
volatile 关键字
- 在多线程环境下使用volatile变量能够保证每次读取前必须先从主内存刷新最新的值,每次写入后必须立即同步回主内存当中。也就是说,volatile关键字修饰的变量看到的随时是自己的最新值。但是volatile关键词不能保证原子性。
- 每次读、取强制从主内存刷数据,能防止字节码指令重排。
- 适用单线程写,多线程读。
- 原则:能不用就不用,不确定的时候也不用。
- 替代方案:Atomic原子操作类。
synchronized 关键字
- 锁对象:锁当前对象
- 锁方法:锁调用方的对象
- 锁代码块:锁调用方的对象(推荐,最小粒度)
这篇关于Java多线程的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-30java最新版本是什么,有什么特性?-icode9专业技术文章分享
- 2024-11-30[开源]27.8K star!这款 Postman 替代工具太火了!
- 2024-11-30Gzip 压缩入门教程:轻松掌握文件压缩技巧
- 2024-11-29开源工具的魅力:让文档管理更“聪明”
- 2024-11-29Release-it开发入门教程
- 2024-11-29Rollup 插件入门教程:轻松掌握模块打包
- 2024-11-29从零到一,产品经理如何玩转项目管理和团队协作
- 2024-11-29如何通过精益生产管理工具帮助项目团队实现精准进度控制?
- 2024-11-29低代码应用开发课程:新手入门与基础教程
- 2024-11-29入门指南:全栈低代码开发课程