03.Java多线程并发库API使用2

1.多个线程之间共享数据的方式探讨

1、如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中有那个共享数据,例如,买票系统就可以这么做。

2、如果每个线程执行的代码不同,这时候需要用不同的Runnable对象,有如下两种方式来实现这些Runnable对象之间的数据共享:

  • 将共享数据封装在另外一个对象中,然后将这个对象逐一传递给各个Runnable对象。每个线程对共享数据的操作方法也分配到那个对象身上去完成,这样容易实现针对该数据进行的各个操作的互斥和通信。
  • 将这些Runnable对象作为某一个类中的内部类,共享数据作为这个外部类中的成员变量,每个线程对共享数据的操作方法也分配给外部类,以便实现对共享数据进行的各个操作的互斥和通信,作为内部类的各个Runnable对象调用外部类的这些方法。

上面两种方式的组合:将共享数据封装在另外一个对象中,每个线程对共享数据的操作方法也分配到那个对象身上去完成,对象作为这个外部类中的成员变量或方法中的局部变量,每个线程的Runnable对象作为外部类中的成员内部类或局部内部类。

总之,要同步互斥的几段代码最好是分别放在几个独立的方法中,这些方法再放在同一个类中,这样比较容易实现它们之间的同步互斥和通信。

极端且简单的方式,即在任意一个类中定义一个static的变量,这将被所有线程共享。

示例代码

 1 package com.chunjiangchao.thread;
 2 /**
 3  * 多线程之间数据共享
 4  * @author chunjiangchao
 5  *
 6  */
 7 public class MultiThreadShareDataDemo {
 8
 9     public static void main(String[] args) {
10         Data data = new Data();
11         new Thread(new IncrementRunnable(data)).start();
12         new Thread(new DecrementtRunnable(data)).start();
13
14         final Data data2 = new Data();
15         new Thread(new Runnable() {
16
17             @Override
18             public void run() {
19                 data2.increment();
20             }
21         }).start();
22         new Thread(new Runnable() {
23
24             @Override
25             public void run() {
26                 data2.decrement();
27             }
28         }).start();
29     }
30     //对共享数据进行增加
31     private static class IncrementRunnable implements Runnable{
32         private Data data ;
33         public IncrementRunnable(Data data){
34             this.data = data;
35         }
36         public void run() {
37             data.increment();
38         }
39     }
40     //对共享数据进行减少
41     private static class DecrementtRunnable implements Runnable{
42         private Data data ;
43         public DecrementtRunnable(Data data){
44             this.data = data;
45         }
46         public void run() {
47             data.decrement();
48         }
49     }
50
51
52     //共享数据
53     private static class Data{
54         private int temp=0;
55         public synchronized  void increment(){
56             temp++;
57             System.out.println(Thread.currentThread()+"中temp的值为:"+temp);
58         }
59         public synchronized void decrement(){
60             temp--;
61             System.out.println(Thread.currentThread()+"中temp的值为:"+temp);
62         }
63     }
64
65 }

2.java5线程并发库的应用(Executors)

static ExecutorService newFixedThreadPool(int nThreads) 创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。(创建固定线程池)

如果在这个线程池里面,创建的线程为3个线程,但是交给的任务时10个任务的话,那么,线程池里面的线程就会运行完3个线程后,接着运行3个线程,直到所有的线程运行完毕。

List<Runnable> shutdownNow()试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表。

shutdown()启动一次顺序关闭,执行以前提交的任务,但不接受新任务。

static ExecutorService newCachedThreadPool()创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。(动态创建线程池,有多少任务,自动创建多少线程)

static ExecutorService  newSingleThreadExecutor():创建单个线程,如果线程死掉了,它会自动找个替补线程补上去。(如何实现线程死掉之后重新启动)?

static ScheduledExecutorService newScheduledThreadPool(int corePoolSize):创建一个定时线程池

实例代码:

 1 package com.chunjiangchao.thread;
 2
 3 import java.util.Date;
 4 import java.util.concurrent.ExecutorService;
 5 import java.util.concurrent.Executors;
 6 import java.util.concurrent.TimeUnit;
 7
 8 /**
 9  * 线程并发库,线程池的使用
10  * @author chunjiangchao
11  *
12  */
13 public class ExecuterDemo {
14
15     public static void main(String[] args) {
16 //        ExecutorService threadPool = Executors.newFixedThreadPool(3);//开了固定的三个线程
17 //        ExecutorService threadPool = Executors.newCachedThreadPool();//开了10个线程
18         ExecutorService threadPool = Executors.newSingleThreadExecutor();//开了一个固定的线程
19         for(int i=0;i<10;i++){
20             final int loop = i;
21             threadPool.execute(new Runnable(){
22                 public void run() {
23                     try {
24                         Thread.sleep(1000);
25                     } catch (InterruptedException e) {
26 //                        e.printStackTrace();
27                     }
28                     System.out.println(Thread.currentThread().getName()+" outer "+loop);
29                 }
30
31             });
32         }
33         /*
34              shutdownNow执行的结果为:
35              pool-1-thread-3 outer
36             pool-1-thread-1 outer
37             pool-1-thread-2 outer * */
38 //        threadPool.shutdownNow();
39         /*shutdown会执行完所有已经提交的任务,不会处理shutdown后提交的任务,而且在后面提交Runnable的时候,
40          * 会抛出异常java.util.concurrent.RejectedExecutionException*/
41         threadPool.shutdown();
42 //        threadPool.execute(new Runnable(){
43 //
44 //            @Override
45 //            public void run() {
46 //                System.out.println("不会进行处理");
47 //            }
48 //
49 //        });
50         //实现定时器效果
51         Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(new Runnable(){
52
53             @Override
54             public void run() {
55                 System.out.println("执行定时器结果"+new Date().toLocaleString());
56             }
57
58         }, 2, 4, TimeUnit.SECONDS);//每隔4s玩一次
59     }
60
61 }

3.Callable&Future

Future取得的结果类型和Callable返回的结果类型必须一致,这是通过泛型来实现的。

Callable要采用ExecutorSevice的submit方法提交,返回的future对象可以取消任务。

CompletionService用于提交一组Callable任务,其take方法返回已完成的一个Callable任务对应的Future对象。

take()   获取并移除表示下一个已完成任务的 Future,如果目前不存在这样的任务,则等待

示例代码

  1 package com.chunjiangchao.thread;
  2
  3 import java.util.Date;
  4 import java.util.concurrent.Callable;
  5 import java.util.concurrent.ExecutionException;
  6 import java.util.concurrent.Executor;
  7 import java.util.concurrent.ExecutorCompletionService;
  8 import java.util.concurrent.ExecutorService;
  9 import java.util.concurrent.Executors;
 10 import java.util.concurrent.Future;
 11
 12 /**
 13  * Callable&Future的使用
 14  * @author chunjiangchao
 15  *
 16  */
 17 public class CallableAndFutureDemo {
 18
 19     public static void main(String[] args) {
 20         ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
 21         //提交单一任务
 22         Future<String> submit = newSingleThreadExecutor.submit(new Callable<String>(){
 23
 24             @Override
 25             public String call() throws Exception {
 26                 printTime();
 27                 mSleep(3000);
 28                 printTime();
 29                 return "我这有返回值,你看看是不是";
 30             }
 31
 32         });
 33         mSleep(500);
 34         try {
 35             String string = submit.get();
 36             System.out.println(string);
 37         } catch (InterruptedException | ExecutionException e) {
 38             e.printStackTrace();
 39         }
 40 //        submit.cancel(true);//可以对任务进行取消
 41         //提交多个任务
 42         Executor executor = Executors.newCachedThreadPool();
 43         ExecutorCompletionService<String> completionService = new ExecutorCompletionService<>(executor);
 44         for(int i=0;i<10;i++){
 45             final int loop = i;
 46             completionService.submit(new Callable<String>(){
 47
 48                 @Override
 49                 public String call() throws Exception {
 50                     mSleep(1000*loop);
 51                     return "提交多任务有返回结果"+loop;
 52                 }
 53
 54             });
 55         }
 56         for(int i=0;i<10;i++){
 57             try {
 58                 Future<String> result = completionService.take();
 59                 printTime();
 60                 System.out.println(result.get());
 61             } catch (InterruptedException e) {
 62                 e.printStackTrace();
 63             } catch (ExecutionException e) {
 64                 e.printStackTrace();
 65             }
 66         }
 67         /*
 68          *     打印 结果如下
 69              2016-4-18 11:57:46
 70             2016-4-18 11:57:49
 71             我这有返回值,你看看是不是
 72             2016-4-18 11:57:49
 73             提交多任务有返回结果0
 74             2016-4-18 11:57:50
 75             提交多任务有返回结果1
 76             2016-4-18 11:57:51
 77             提交多任务有返回结果2
 78             2016-4-18 11:57:52
 79             提交多任务有返回结果3
 80             2016-4-18 11:57:53
 81             提交多任务有返回结果4
 82             2016-4-18 11:57:54
 83             提交多任务有返回结果5
 84             2016-4-18 11:57:55
 85             提交多任务有返回结果6
 86             2016-4-18 11:57:56
 87             提交多任务有返回结果7
 88             2016-4-18 11:57:57
 89             提交多任务有返回结果8
 90             2016-4-18 11:57:58
 91             提交多任务有返回结果9
 92          */
 93
 94     }
 95     private static void mSleep(long time){
 96         try {
 97             Thread.sleep(time);
 98         } catch (InterruptedException e) {
 99             e.printStackTrace();
100         }
101     }
102     private static void printTime(){
103         System.out.println(new Date().toLocaleString());
104     }
105
106 }

4.java5的线程锁技术

Lock的使用

时间: 2024-11-05 23:31:14

03.Java多线程并发库API使用2的相关文章

04.Java多线程并发库API使用3

1.java5的Semaphere同步工具 Semaphore可以维护当前访问自身的线程个数,并提供了同步机制.使用Semaphore可以控制同时访问资源的线程个数,例如,实现一个文件允许的并发访问数. Semaphore实现的功能就类似银行有6个窗口,12个人有业务要操作,那么同时只能有6个人占用窗口,当有的人业务操作完毕之后,让开位置,其它等待的人群中,有一人可以占用当前窗口,操作自己的业务. 另外等待的5个人中可以是随机获得优先机会,也可以是按照先来后到的顺序获得机会,这取决于构造Sema

对JAVA多线程 并发编程的理解

对JAVA多线程并发编程的理解 Java多线程编程关注的焦点主要是对单一资源的并发访问,本文从Java如何实现支持并发访问的角度,浅析对并发编程的理解,也算是对前段时间所学的一个总结. 线程状态转换 Java语言定义了5中线程状态,在任何一个时间点,一个线程只能有且只有其中一种状态,这5中状态分别是: ?  新建(New):创建后尚未启动的线程处于这种状态 ?  运行(Runable):Runable包括了操作系统线程状态中的Running和Ready,也就是处于此状态的线程可能正在执行,也有可

Java多线程并发09——如何实现线程间与线程内数据共享

本文将为各位带来 Java 阻塞队列相关只是.关注我的公众号「Java面典」了解更多 Java 相关知识点. 线程间数据共享 Java 里面进行多线程通信的主要方式就是共享内存的方式,共享内存主要的关注点有两个:可见性和有序性原子性.Java 内存模型(JMM)解决了可见性和有序性的问题,而锁解决了原子性的问题,理想情况下我们希望做到"同步"和"互斥".有以下常规实现方法: 将数据抽象成一个类 将数据抽象成一个类,并将对这个数据的操作作为这个类的方法,这么设计可以和

Java高并发秒杀API之业务分析与DAO层

课程介绍 高并发和秒杀都是当今的热门词汇,如何使用Java框架实现高并发秒杀API是该系列课程要研究的内容.秒杀系列课程分为四门,本门课程是第一门,主要对秒杀业务进行分析设计,以及DAO层的实现.课程中使用了流行的框架组合SpringMVC+Spring+MyBatis,还等什么,赶快来加入吧! 第1章 课程介绍 本章介绍秒杀系统的技术内容,以及系统演示.并介绍不同程度的学员可以学到什么内容. 第2章 梳理所有技术和搭建工程 本章首先介绍秒杀系统所用框架和技术点,然后介绍如何基于maven搭建项

2017.4.26 慕课网--Java 高并发秒杀API(一)

Java高并发秒杀API系列(一) -----------------业务分析及Dao层 第一章 课程介绍 1.1 内容介绍及业务分析 (1)课程内容 1 SSM框架的整合使用 2 秒杀类系统需求理解和实现 3 常用技术解决高并发问题 (2)SSM框架 (3)为何选择秒杀系统 1 秒杀系统具有典型的"事务"特性 2 秒杀/红包类需求越来越常见 3 面试常用问题 1.3 项目效果演示 第二章 梳理所有技术和搭建工程 2.1 相关技术介绍 2.2 创建项目和依赖 第三章 秒杀业务分析 3.

java 多线程并发问题总结

java 多线程并发主要通过关键字synchronized实现 Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行.另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块. 二.然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该ob

Java多线程并发技术

Java多线程并发技术 参考文献: http://blog.csdn.net/aboy123/article/details/38307539 http://blog.csdn.net/ghsau/article/category/1707779 http://www.iteye.com/topic/366591 JAVA多线程实现方式主要有三种:继承Thread类.实现Runnable接口.使用ExecutorService.Callable.Future实现有返回结果的多线程.其中前两种方式

知识链-Java多线程并发

Java多线程并发 java并发容器(Map.List.BlockingQueue)

imooc课程:Java高并发秒杀API 记录

Java高并发秒杀API之业务分析与DAO层 Java高并发秒杀API之Service层 Java高并发秒杀API之web层 Java高并发秒杀API之高并发优化 除了并发部分外的这个web开发的总结:https://www.imooc.com/video/11737 springmvc运行流程 BOOTSTRAP 和 JS 的使用技巧.(模块化.不混乱.抽取字典方便修改) JQ插件(countDown && cookie 等) 原文地址:https://www.cnblogs.com/a