1、多个线程行为不一致共同操作一个数据
如果每个线程执行的代码不同,这时候需要用不同的 Runnable 对象:
有如下两种方法:
方法1)将共享数据封装在另外一个对象中,然后将这个对象逐一传递给各个 Runnable 对象。每个线程对共享数据的操作方法也分配到那个对象身上去完成,这样容易实现针对该数据进行的各个操作的互斥和通信。见示列1:ShareDataThreadDifferent
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
public class ShareDataThreadDifferent { public static void main(String[] args) { ShareData1 shareData = new ShareData1(); for (int i = 0; i < 4; i++) { if (i % 2 == 0) {//%是求模运算符 /是除运算符 new Thread(new RunnableCusToInc1(shareData), "Thread " + i) .start(); } else { new Thread(new RunnableCusToDec(shareData), "Thread " + i) .start(); } } } } /** * 共享数据类 **/ class ShareData1 { private int num = 10; public synchronized void inc() { num++; System.out.println(Thread.currentThread().getName() + ": invoke inc method num =" + num); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } public synchronized void dec() { num--; System.out.println(Thread.currentThread().getName() + ": invoke dec method num =" + num); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } // 封装共享数据类的Runnable类1 class RunnableCusToInc1 implements Runnable { // 封装共享数据 private ShareData1 shareData; public RunnableCusToInc1(ShareData1 data) { this.shareData = data; } public void run() { for (int i = 0; i < 5; i++) { shareData.inc(); } } } // 封装共享数据类Runnable类2 class RunnableCusToDec implements Runnable { // 封装共享数据 private ShareData1 shareData; public RunnableCusToDec(ShareData1 data) { this.shareData = data; } public void run() { for (int i = 0; i < 5; i++) { shareData.dec(); } } }
运行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
Thread 0: invoke inc method num =11 Thread 0: invoke inc method num =12 Thread 3: invoke dec method num =11 Thread 2: invoke inc method num =12 Thread 1: invoke dec method num =11 Thread 1: invoke dec method num =10 Thread 2: invoke inc method num =11 Thread 2: invoke inc method num =12 Thread 2: invoke inc method num =13 Thread 2: invoke inc method num =14 Thread 3: invoke dec method num =13 Thread 0: invoke inc method num =14 Thread 3: invoke dec method num =13 Thread 3: invoke dec method num =12 Thread 3: invoke dec method num =11 Thread 1: invoke dec method num =10 Thread 1: invoke dec method num =9 Thread 1: invoke dec method num =8 Thread 0: invoke inc method num =9 Thread 0: invoke inc method num =10
方法2)将这些 Runnable 对象作为某一个类中的内部类,共享数据作为这个外部类中的成员变量,每个线程对共享数据的操作方法也分配给外部类,以便实现对共享数据进行的各个操作的互斥和通信,作为内部类的各个Runnable 对象调用外部类的这些方法。见示列1:ShareDataThreadDifferent2
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
public class ShareDataThreadDifferent2 {//外部类 public static void main(String[] args) { // 公共数据 final ShareData2 shareData = new ShareData2();//共享数据类 for (int i = 0; i < 4; i++) { if (i % 2 == 0) { new Thread(new Runnable() {//内部类 public void run() { for (int i = 0; i < 5; i++) { shareData.inc();//对共享数据的操作 } } }, "Thread " + i).start(); } else { new Thread(new Runnable() { public void run() { for (int i = 0; i < 5; i++) { shareData.dec(); } } }, "Thread " + i).start(); } } } } class ShareData2 { private int num = 10; public synchronized void inc() { num++; System.out.println(Thread.currentThread().getName() + ": invoke inc method num =" + num); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } public synchronized void dec() { num--; System.err.println(Thread.currentThread().getName() + ": invoke dec method num =" + num); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }
运行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
Thread 0: invoke inc method num =11 Thread 2: invoke inc method num =12 Thread 2: invoke inc method num =13 Thread 3: invoke dec method num =12 Thread 3: invoke dec method num =11 Thread 1: invoke dec method num =10 Thread 1: invoke dec method num =9 Thread 1: invoke dec method num =8 Thread 1: invoke dec method num =7 Thread 1: invoke dec method num =6 Thread 3: invoke dec method num =5 Thread 2: invoke inc method num =6 Thread 0: invoke inc method num =7 Thread 0: invoke inc method num =8 Thread 2: invoke inc method num =9 Thread 3: invoke dec method num =8 Thread 2: invoke inc method num =9 Thread 0: invoke inc method num =10 Thread 3: invoke dec method num =9 Thread 0: invoke inc method num =10
2、多个线程行为一致共同操作一个数据:
如果每个线程执行的代码相同,可以使用同一个 Runnable 对象,这个Runnable 对象中有那个共享数据, 例如:买票系统就可以这么做
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
public class ShareDataThreadUniformity { public static void main(String[] args) { ShareData shareData = new ShareData(); for (int i = 0; i < 4; i++) { new Thread(new RunnableCusToInc(shareData),"Thread "+ i).start(); } } } class ShareData { private int num = 10; public synchronized void inc() { num++; System.out.println(Thread.currentThread().getName() + ": invoke inc method num =" + num); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } class RunnableCusToInc implements Runnable { private ShareData shareData; public RunnableCusToInc(ShareData data) { this.shareData = data; } public void run() { for (int i = 0; i < 5; i++) { shareData.inc(); } } }
运行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
Thread 0: invoke inc method num =11 Thread 3: invoke inc method num =12 Thread 2: invoke inc method num =13 Thread 2: invoke inc method num =14 Thread 2: invoke inc method num =15 Thread 2: invoke inc method num =16 Thread 2: invoke inc method num =17 Thread 1: invoke inc method num =18 Thread 1: invoke inc method num =19 Thread 1: invoke inc method num =20 Thread 1: invoke inc method num =21 Thread 1: invoke inc method num =22 Thread 3: invoke inc method num =23 Thread 0: invoke inc method num =24 Thread 3: invoke inc method num =25 Thread 3: invoke inc method num =26 Thread 3: invoke inc method num =27 Thread 0: invoke inc method num =28 Thread 0: invoke inc method num =29 Thread 0: invoke inc method num =30