Java多线程,线程同步synchronized,线程死锁【线程池常规用法】多线程并发处理
2016-07-14 09:01
976 查看
工作内容:
1.线程同步:synchronized (锁类)
2.线程死锁(Thread.join(),Synchronized)
3.生产者与消费者模式
4.线程练习
5.线程池
6.多线程并发ThreadLocal与Synchronized
线程同步:
Synchronized(Object){
代码块 }
Public static synchronized void method(){
代码块 }
尽量用在最细致的地方(精确位置)
线程死锁:发生在请求同步方法,同步方法请求同一个对象时
实例1:线程死锁的实现1(Synchronized)
已锁定obj2-----正在锁定obj1...
已锁定obj1-----正在锁定obj2...
说明:两个方法锁定了第一个对象后都没有成功锁定另外一个对象造成死锁
实例1:线程死锁的实现2(Thread.join())
执行join
执行thread
执行thread完成
执行完毕
实例2:(通过Runnable实现数据共享)
5.线程池:
Java通过Executors提供四种线程池,分别为:
1.newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
2.newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
3.newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
定期执行
4.newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO,
LIFO, 优先级)执行
2种执行方式:
对ThreadLocal的理解,【可以点进去看看】
ThreadLocal:“以空间换时间”的方式处理多线程并发(操作同一个对象)问题——为每个线程创建一个对应线程的对象的副本
Synchronized:"以时间换空间"的方式处理多线程并发(操作同一个对象)问题——同一时刻只准一个线程访问该对象
最常见的ThreadLocal使用场景为 用来解决 数据库连接、Session管理等。
实例:数据库链接
实例:会话控制
private static final ThreadLocal threadSession = new ThreadLocal();
public static Session getSession() throws InfrastructureException {
Session s = (Session) threadSession.get();
try {
if (s == null) {
s = getSessionFactory().openSession();
threadSession.set(s);
}
} catch (HibernateException ex) {
throw new InfrastructureException(ex);
}
return s;
}
1.线程同步:synchronized (锁类)
2.线程死锁(Thread.join(),Synchronized)
3.生产者与消费者模式
4.线程练习
5.线程池
6.多线程并发ThreadLocal与Synchronized
线程同步:
Synchronized(Object){
代码块 }
Public static synchronized void method(){
代码块 }
尽量用在最细致的地方(精确位置)
线程死锁:发生在请求同步方法,同步方法请求同一个对象时
实例1:线程死锁的实现1(Synchronized)
private Object obj1 = new Object(),obj2 = new Object(); //..........同时调用下列2个方法 private void startlock2() { new Thread(){ @Override public void run() { synchronized (obj1){ try { Thread.sleep(1000);//睡眠1秒 } catch (InterruptedException e) { e.printStackTrace(); } Log.e("-------","已锁定obj1-----正在锁定obj2...."); synchronized(obj2){ Log.e("-------","已锁定obj1并且锁定了obj2"); } } } }.start(); } private void startlock1() { new Thread(){ @Override public void run() { synchronized (obj2){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } Log.e("-------","已锁定obj2-----正在锁定obj1..."); synchronized(obj1){ Log.e("-------","已锁定obj2并且锁定了obj1"); } } } }.start(); }得到结果:
已锁定obj2-----正在锁定obj1...
已锁定obj1-----正在锁定obj2...
说明:两个方法锁定了第一个对象后都没有成功锁定另外一个对象造成死锁
实例1:线程死锁的实现2(Thread.join())
private void startlock2() { thread = new Thread() { @Override public void run() { Log.e("-------", "执行thread"); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } Log.e("-------", "执行thread完成"); } }; new Thread() { @Override public void run() { Log.e("-------", "执行join"); try { thread.start(); thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } Log.e("-------", "执行完毕"); } }.start(); }运行结果:【join的线程先执行完成才会继续执行原线程】
执行join
执行thread
执行thread完成
执行完毕
实例2:(通过Runnable实现数据共享)
//摇出三个36以内的随机号码 import java.util.ArrayList; public class Test4 { public static void main(String[] args) { ProduceNum num = new ProduceNum(); new Thread(num).start(); new Thread(num).start(); new Thread(num).start(); //打印语句可能先于线程的执行,先暂停主线程 try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(ProduceNum.list); } } class ProduceNumimplements Runnable { static ArrayList<Integer> list = new ArrayList<Integer>(); @Override public void run() { GetRondom.getNum(); } } //产生随机数的类0-37前闭后开 class GetRondom { public static void getNum() { int x = (int) (Math.random() * 37); ProduceNum.list.add(x); } }
5.线程池:
Java通过Executors提供四种线程池,分别为:
1.newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
public static void main(String[] args) { ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { final int index = i; try { Thread.sleep(index * 1000); } catch (InterruptedException e) { e.printStackTrace(); } cachedThreadPool.execute(new Runnable() { public void run() { System.out.println(index); } }); } }
2.newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
fixedThreadPool.execute(new Runnable() { public void run() { try { System.out.println(index); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } });
3.newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5); scheduledThreadPool.schedule(new Runnable() { public void run() { System.out.println("delay 3 seconds"); } }, 3, TimeUnit.SECONDS);//延迟3秒执行 }
定期执行
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5); scheduledThreadPool.scheduleAtFixedRate(new Runnable() { public void run() { System.out.println("delay 1 seconds, and excute every 3 seconds"); } }, 1, 3, TimeUnit.SECONDS); //延迟1秒执行,每3秒执行一次 }
4.newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO,
LIFO, 优先级)执行
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); singleThreadExecutor.execute(new Runnable() { public void run() { try { System.out.println(index); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } });
2种执行方式:
single.execute(new Runnable() {//同步 @Override public void run() { } }); single.submit(new Runnable c277 () {//提交 @Override public void run() { } });6.多线程并发问题
对ThreadLocal的理解,【可以点进去看看】
ThreadLocal:“以空间换时间”的方式处理多线程并发(操作同一个对象)问题——为每个线程创建一个对应线程的对象的副本
Synchronized:"以时间换空间"的方式处理多线程并发(操作同一个对象)问题——同一时刻只准一个线程访问该对象
最常见的ThreadLocal使用场景为 用来解决 数据库连接、Session管理等。
实例:数据库链接
private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>() { public Connection initialValue() { return DriverManager.getConnection(DB_URL); } }; public static Connection getConnection() { return connectionHolder.get(); }
实例:会话控制
private static final ThreadLocal threadSession = new ThreadLocal();
public static Session getSession() throws InfrastructureException {
Session s = (Session) threadSession.get();
try {
if (s == null) {
s = getSessionFactory().openSession();
threadSession.set(s);
}
} catch (HibernateException ex) {
throw new InfrastructureException(ex);
}
return s;
}
相关文章推荐
- java流程控制
- java常用排序算法
- Spring4.0系列9-websocket简单应用
- struts2--配置(一般、常量、页面配置)
- 使用Spring Boot来加速Java web项目的开发
- Java中输入——输出——数据类型转化…
- Java中的ArrayList/List使用方法
- JAVA 十大算法
- Java中字节流和异常处理
- Spring系列之简单的应用实例
- SpringMVC中使用Interceptor拦截器
- 如何在Java中构造多维动态数组以及多维动态数组的使用
- [置顶] Debugging PL-SQL calls from Java Session Using Eclipse and SQL Developer
- Dubbo与Zookeeper、SpringMVC整合和使用(负载均衡、容错)
- Eclipse快捷键与使用技巧总结
- 01 java开发前小知识
- java中List、Set、Map、Properties集合的遍历方法总结
- Java中的参数传递问题图解
- Java 集合 LinkedList的ListIterator
- Java-try-with-resource