package com.nuanshui.frms.native1.thread;
/**
* @author liyy
* @description:多线程通信
* @date 2019-03-27 19:58
* @program frms-parent
*/
public class MultiThreadShareData {
public static void main(String[] args){
//100票 10个售票员(票务对象)对10个窗口(线程)去卖票 1 99 1 99 1 99
//100票 1个售票员去(票务对象)对10个窗口(线程)去卖票 1 99
ShareTicket shareTicket = new ShareTicket();
/*ShareTicket shareTicket = new ShareTicket();
for(int i=0;i<10;i++){
new Thread(shareTicket).start();
}*/
for(int i=0;i<120;i++){
new Thread(new Runnable() {
@Override
public void run() {
shareTicket.sell();
}
}).start();
}
}
/*static class ShareTicket implements Runnable{
public int ticketTotal = 100;
@Override
public void run() {
if(ticketTotal>0){
System.out.println(Thread.currentThread().getName()+"消费一张票");
ticketTotal -- ;
System.out.println("剩余票数:"+ticketTotal);
}
}
}*/
static class ShareTicket{
public int ticketTotal = 100;
public void sell() {
synchronized (this){
if(ticketTotal>0){
System.out.println(Thread.currentThread().getName()+"消费一张票");
ticketTotal -- ;
System.out.println("剩余票数:"+ticketTotal);
}else{
System.out.println("票买完了");
}
}
}
}
}
简单的一个免票任务。new 120个线程同时去买票。多线程同时去操作共享变量总票数。分析一下。就是一个任务,交给多个线程同时去执行。要保证每个线程读取数据是正确的。那么就相当于一个售票员开了10个窗口卖100张票。每次只能操作一个窗口。synchronized (this)操作添加互斥锁。保证当前线程操作时其他线程都处于等待状态。
下面还有一个多任务。多线程执行操作某一个变量的场景:
package com.nuanshui.frms.native1.thread;
/**
* @author liyy
* @description:
* @date 2019-03-27 20:24
* @program frms-parent
*/
public class Business1 {
public static int data = 0;
//设计四个线程,其中两个线程每次对 data 增加 1,另外两个线程每次对 data 减少 1。
//负责对data增1
public synchronized void add(){
System.out.println("before:"+Thread.currentThread().getName()+"对data增1前data是:"+data);
data++;
System.out.println("after:"+Thread.currentThread().getName()+"对data增1后data是:"+data);
}
public synchronized void minus(){
System.out.println("before:"+Thread.currentThread().getName()+"对data减1前data是:"+data);
data--;
System.out.println("after:"+Thread.currentThread().getName()+"对data减1后data是:"+data);
}
}
package com.nuanshui.frms.native1.thread;
/**
* @author liyy
* @description:
* @date 2019-03-27 20:30
* @program frms-parent
*/
public class MultiThreadShareData1 {
public static void main(String[] args){
Business1 business1 = new Business1();
for(int i=0;i<2;i++){
new Thread(new Runnable() {
@Override
public void run() {
business1.add();
}
}).start();
}
for(int i=0;i<2;i++){
new Thread(new Runnable() {
@Override
public void run() {
business1.minus();
}
}).start();
}
}
}
问题关键是锁对象必须是一样的。这样才能保证每次线程都能拿到同一把锁。并让其他线程等待。
总结如下:
多个线程之间共享数据主要关注两点就行:一是什么任务?几个任务?二是几个线程?记住 一点:几个任务和几个线程是没有关系的!100 个线程可以执行一个任务,也可以执行 2 个任务,3 个任务……
如果只有一个任务,那说明多个线程执行一个任务,我们只要实现一个 Runnable 接口,把公共 data 放进 Runnable,把任务放进去 run()
中即可(任务注意要同步),然后开启 N 个线程去执行这个任务即可;如果有 M 个任务,那我们新建一个专门执行任务的类,把公共的 data 放进类中,把任务作为类中的同步方法即可,然后开启 N 个线程,每个线程中扔一个 Runnable,按照要求执行任务类中的方法即可。