您的位置:首页 > 编程语言 > Java开发

java并发编程之:线程共享数据的方式

2017-06-25 00:00 405 查看

java并发编程之:线程共享数据的方式

多个线程对共同数据的访问的实现,要根据情况而定

(1)当访问共同的代码的时候:可以使用同一个Runnable对象,这个Runnable对象中有这个共享数据,比如卖*系统就可以这么做。或者这个共享数据封装在一个对象当中,然后对这个对象加锁,也可以实现数据安全访问。

(2)当各个线程访问的代码不同时:这时候要使用不同的Runnable对象,有两种实现方式:

a)将共享数据封装在另一个对象当中,然后将这个对象逐一的转递给各个Runnable对象。操作数据的方法也放进这个对象当中。这样容易实现各个线程对这个数据的同步和共享。

b)将Runnable对象作为某一个类中的内部类,共享数据作为这个外部类的成员变量,每个线程对共享数据的访问也交给外部类的方法,比便对共享数据的互斥和通信。Runnable对象调用外部类的操作这个共享数据的方法。

还有一种方式是a)和b)的结合实现,把共享数据封装到一个对象当中去,这个对象也实现对这个共享数据的操作,这个对象作为外部类的成员变量。然后再创建多个Runnable对象做为内部类,操作这个对象。

一、每个线程执行的代码相同,可以使用同一个Runnable对象

public class SellTicket {

public static void main(String[] args) {
Ticket t = new Ticket();
new Thread(t).start();
new Thread(t).start();
}

}
class Ticket implements Runnable{
private int ticket = 10;
@Override
public void  run() {
while(ticket>0){
synchronized (this){
if(ticket > 0){
ticket--;
System.out.println("当前*数为:"+ticket);
}
}
}
}
}

二 1)当各个线程访问的代码不同时:这时候要使用不同的Runnable对象,将共享数据封装在另一个对象当中,然后将这个对象逐一的转递给各个Runnable对象。操作数据的方法也放进这个对象当中。这样容易实现各个线程对这个数据的同步和共享

public class MultiThreadShareData {
public static void main(String[] args) {
ShareData1 data2 = new ShareData1();
new Thread(new MyRunnable1(data2)).start();
new Thread(new MyRunnable2(data2)).start();
}
}

class MyRunnable1 implements Runnable{
private ShareData1 data1;
public MyRunnable1(ShareData1 data1){
this.data1 = data1;
}
public void run() {
data1.decrement();

}
}

class MyRunnable2 implements Runnable{
private ShareData1 data1;
public MyRunnable2(ShareData1 data1){
this.data1 = data1;
}
public void run() {
data1.increment();
}
}

class ShareData1 {
private int j = 0;
public synchronized void increment(){
j++;
}

public synchronized void decrement(){
j--;
}
}

二 2)把共享数据封装到一个对象当中去,这个对象也实现对这个共享数据的操作,这个对象作为外部类的成员变量。然后再创建多个Runnable对象做为内部类,操作这个对象

public class MultiThreadShareData {
public static void main(String[] args) {
final ShareData1 data1 = new ShareData1();//现在为局部变量,也可以写成类变量static类型(在main方法外声明)
new Thread(new Runnable(){
@Override
public void run() {
data1.decrement();

}
}).start();
new Thread(new Runnable(){
@Override
public void run() {
data1.increment();

}
}).start();
}
}

class MyRunnable1 implements Runnable{
private ShareData1 data1;
public MyRunnable1(ShareData1 data1){
this.data1 = data1;
}
public void run() {
data1.decrement();

}
}

class MyRunnable2 implements Runnable{
private ShareData1 data1;
public MyRunnable2(ShareData1 data1){
this.data1 = data1;
}
public void run() {
data1.increment();
}
}

class ShareData1 {
private int j = 0;
public synchronized void increment(){
j++;
}

public synchronized void decrement(){
j--;
}
}

总结:对于要是下同步互斥的代码要放在不同的方法中,并且放在同一个对象当中,容易实现互斥和通信,并且也有利于日后的维护。这样思路也很清晰。

多线程间进行通讯例子:(wait(),notify())

public class TraditionalThreadCommunication {
/**
* @param args
*/
public static void main(String[] args) {

final Business business = new Business();
new Thread(
new Runnable() {

@Override
public void run() {
for(int i=1;i<=20;i++){
business.sub(i);
}
}
}
).start();
for(int i=1;i<=20;i++){
business.main(i);
}
}

}
class Business {
private boolean bShouldSub = true;
public synchronized void sub(int i){
while(!bShouldSub){//建议用while 因为线程有时候会被假唤醒,线程没有被通知的时候被唤醒
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int j=1;j<=10;j++){
System.out.println("sub thread sequence of " + j + ",loop of " + i);
}
bShouldSub = false;
this.notify();
}

public synchronized void main(int i){
while(bShouldSub){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int j=1;j<=100;j++){
System.out.println("main thread sequence of " + j + ",loop of " + i);
}
bShouldSub = true;
this.notify();
}
}

锁是上在代表要操作的资源的类内部方法中的,而不是线程代码中的。

synchronized 锁什么对象,wait 和 notify 就作用在什么对象上。否则会报错。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java
相关文章推荐