博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
线程之间的通信(二)
阅读量:4073 次
发布时间:2019-05-25

本文共 3898 字,大约阅读时间需要 12 分钟。

线程之间通信

  • 概念:
    线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体,线程间的通信就是成为整体的比用方式之一。当线程存在通信指挥,系统间的交互性会更强,在提高CPU利用率的同时还会使开发人员对线程任务处理的过程中进行有效的把控和监督。

使用wait/notify方法实现线程间的通信(这两个方法都是Ojbect的类方法,也就是说java为所有的对象都提供了这两个方法)。

  1. wait和notify必须配合synchronized关键字使用。
  2. wait方法释放锁,notify方法不释放锁。
public class ListAdd {	private volatile List
list = new ArrayList<>(); public void add(){ list.add("add to list"); } public int size(){ return list.size(); } public static void main(String[] args) { final ListAdd listAdd =new ListAdd(); //声明一个锁 //使用wait和notify时,必须配合synchronized使用 final Object lock = new Object(); Thread t1 = new Thread(new Runnable(){ @Override public void run() { try{ synchronized (lock) { for(int i = 0; i < 10; i++){ listAdd.add(); System.out.println("当前线程:" + Thread.currentThread().getName() + "添加一个元素"); Thread.sleep(500); if(listAdd.size() == 5){ System.out.println("通知发出!"); lock.notify(); //通知t2,不释放锁,直到线程执行完毕才释放锁。 } } } } catch(InterruptedException e){ e.printStackTrace(); } }},"t1"); Thread t2 = new Thread(new Runnable(){ @Override public void run() { try{ synchronized (lock) { if(listAdd.size() != 5){ lock.wait(); //释放锁 } } } catch (InterruptedException e){ e.printStackTrace(); } System.out.println("当前线程:" + Thread.currentThread().getName() + "添收到通知线程停止"); throw new RuntimeException(); }},"t2"); t2.start(); t1.start(); }}/*打印结果: 当前线程:t1添加一个元素 当前线程:t1添加一个元素 当前线程:t1添加一个元素 当前线程:t1添加一个元素 当前线程:t1添加一个元素 通知发出! 当前线程:t1添加一个元素 当前线程:t1添加一个元素 当前线程:t1添加一个元素 当前线程:t1添加一个元素 当前线程:t1添加一个元素 当前线程:t2添收到通知线程停止 Exception in thread "t2" java.lang.RuntimeException at com.jt.thread02.ListAdd$2.run(ListAdd.java:59) at java.lang.Thread.run(Unknown Source)*/

ThreadLocal

  • 概念:
    线程局部变量,是一种多线程间并发访问变量的解决方案。与synchronized等加锁的方式不同,ThreadLocal完全不提供锁,而使用空间换时间的手段,为每个变量提供变量的独立副本,以保证线程安全。从性能上来说,ThreadLocal不具备绝对的优势,在并发不是很高的时候,加锁的性能会更好,但作为一套与锁安全无关的线程安全解决方案,在高并发量或者竞争激烈的场景,使用ThreadLocal可以在一定程度上减少锁竞争。
public class ConnThreadLocal {	final ThreadLocal
str = new ThreadLocal<>(); public void setStr(String value){ str.set(value); } public void getStr(){ System.out.println(Thread.currentThread().getName()+":"+this.str.get()); } public static void main(String[] args) { final ConnThreadLocal ctl = new ConnThreadLocal(); Thread t1 = new Thread(new Runnable(){ @Override public void run() { ctl.setStr("zhangsan"); ctl.getStr();//当前线程获取值 }},"t1"); Thread t2 = new Thread(new Runnable(){ @Override public void run() { ctl.getStr();//当前线程获取值 }},"t2"); t1.start(); t2.start(); }}/** * 打印结果: * t1:zhangsan * t2:null * */

单例&多线程

单例模式,最常见的就是饥饿模式和懒汉模式,一个直接实例化对象, 一个在调用方法时进行实例化对象。在多线程模式中,考虑到性能和线程安全问题,我们一般选择两种比较经典的单例模式,在性能提高的同时,有保证了线程安全。

  • dubble check instance.
  • static inner class.
public class DubboCheck {	private static DubboCheck dc;		public static DubboCheck getDubboCheck(){		if(null == dc){			try{				Thread.sleep(1000); //三个线程都阻塞到了这里			} catch (InterruptedException e){				e.printStackTrace();			}			synchronized (DubboCheck.class) {				if(null == dc){					dc = new DubboCheck();				}			}		}		return dc;	}		public static void main(String[] args) {		Thread t1 = new Thread(new Runnable(){			@Override			public void run() {				System.out.println(DubboCheck.getDubboCheck().hashCode());			}},"t1");				Thread t2 = new Thread(new Runnable(){			@Override			public void run() {				System.out.println(DubboCheck.getDubboCheck().hashCode());			}},"t2");				Thread t3 = new Thread(new Runnable(){			@Override			public void run() {				System.out.println(DubboCheck.getDubboCheck().hashCode());			}},"t3");				t1.start();		t2.start();		t3.start();	}}
public class InnerClass {	private static class Singletion{		private static Singletion single = new Singletion();	}		public static Singletion getSingletion(){		return Singletion.single;	}}

转载地址:http://fbkni.baihongyu.com/

你可能感兴趣的文章
医疗行业运用企业云盘可以带来什么样的提升
查看>>
媒体广告业如何运用云盘提升效率
查看>>
IOS开发的开源库
查看>>
Jenkins - sonarqube 代码审查
查看>>
Jenkins + Docker + SpringCloud 微服务持续集成(一)
查看>>
Jenkins + Docker + SpringCloud 微服务持续集成 - 单机部署(二)
查看>>
Jenkins + Docker + SpringCloud 微服务持续集成 - 高可用集群部署(三)
查看>>
Linux 粘滞位 suid sgid
查看>>
C#控件集DotNetBar安装及破解
查看>>
Winform皮肤控件IrisSkin4.dll使用
查看>>
Winform多线程
查看>>
C# 托管与非托管
查看>>
Node.js中的事件驱动编程详解
查看>>
mongodb管理与安全认证
查看>>
nodejs内存控制
查看>>
nodejs Stream使用中的陷阱
查看>>
MongoDB 数据文件备份与恢复
查看>>
MongoDB数据库插入、更新和删除操作详解
查看>>
MongoDB文档(Document)全局唯一ID的设计思路
查看>>
mongoDB简介
查看>>