java多线程信息共享

Posted 浅滩浅

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java多线程信息共享相关的知识,希望对你有一定的参考价值。

上篇文章知识介绍了多线程的创建和启动问题,各个子线程和子线程或者说子线程和main线程没有信息的交流,这篇文章主要探讨线程之间信息共享以及交换问题。这篇文章主要以一个卖票例子来展开。

继承Thread重写run方法进行实现

初始代码:

public class Tickect1 {
    public static void main(String[] args) {

        //创建四个线程进行测试
        new Thread3().start();
        new Thread3().start();
        new Thread3().start();
        new Thread3().start();

    }
}

class Thread3 extends Thread{
    private static int tickets = 100;//总票数
    @Override
    public void run() {
        while(true){
            if(tickets<=0){
                break;
            }else{
                System.out.println(Thread.currentThread().getName()+" "+tickets);
                tickets--;
            }
        }
    }
}

错误答案:卖了103张票

分析原因:1.类似于i++的操作不是原子操作


四个进程有四个工作缓存,每次都是修改工作缓存的数据,而且四个工作缓存之间的数据无法共享,倒置在缓存1中已经tickets-1,但是缓存2中tickets又无法获取1中缓存的数据所以票会增大,所以出现103
2.关键步骤缺少加锁操作(获取票数和对票数-1的操作同时执行会出现问题)

改进的代码:这个代码有bug,测试答案还是103

public class Tickect1 {
    public static void main(String[] args) {

        //创建四个线程进行测试
        new Thread3().start();
        new Thread3().start();
        new Thread3().start();
        new Thread3().start();

    }
}

class Thread3 extends Thread{
    private static volatile int tickets = 100;//总票数
    @Override
    public void run() {
        while(true){
            sale();
            if(tickets<=0) break;
        }
    }

    public synchronized void sale(){//对数据修改进行加锁(同一时刻只能一个线程执行)
        if(tickets>0){
            System.out.println(Thread.currentThread().getName()+" "+tickets);
            tickets--;
        }

    }
}

实现Runnable的run方法进行实现

public class Ticket2 {
    public static void main(String[] args) {
        Thread4 t = new Thread4();
        new Thread(t).start();
        new Thread(t).start();
        new Thread(t).start();
        new Thread(t).start();

    }
}


class Thread4 implements Runnable{

    private volatile int tickets=100;//volatile起到通知各个线程缓存区的数据是否修改,如果修改就刷新缓冲区数据(变量副本的解决方法)
    String str = new String("");//对这个对象加锁
    @Override
    public void run() {
        while (true){
           //sale();方式1
            synchronized (str){//代码快加锁(方式2)
                if(tickets>0){
                    System.out.println(Thread.currentThread().getName()+" "+tickets);
                    tickets--;
                }
            }
          if(tickets<=0) break;
        }
    }
    public synchronized void sale(){//synchronized对数据修改进行加锁(同一时刻只能一个线程执行)
        if(tickets>0){//必须在这里判断,if放在外面会出现错误
            System.out.println(Thread.currentThread().getName()+" "+tickets);
            tickets--;
        }

    }
}

volatile关键字测试

public class ThreadDemo2
{
	public static void main(String args[]) throws Exception 
	{
		TestThread2 t = new TestThread2();
		t.start();
		Thread.sleep(2000);
		t.flag = false;
		System.out.println("main thread is exiting");
	}
}

class TestThread2 extends Thread
{
	//boolean flag = true;   //子线程不会停止
	volatile boolean flag = true;  //用volatile修饰的变量可以及时在各线程里面通知
	public void run() 
	{
		int i=0;
		while(flag)
		{
			i++;			
		}
		System.out.println("test thread3 is exiting");
	}	
} 

以上是关于java多线程信息共享的主要内容,如果未能解决你的问题,请参考以下文章

多线程编程

java基础入门-多线程同步浅析-以银行转账为样例

Java学习多线程2

java多线程基础

什么是Java多线程编程?

[Python3] 043 多线程 简介