• 【多线程 3】多线程间的变量共享方式


    上篇博客说到了多线程的创建方式,本篇博客说说自己对于多个线程间的共享变量的理解。

    一、概述

    首先,分析集中不同的变量共享场景:

    1,多个线程执行同样的代码

    在这种情况下,可以使用同一个Runnable对象(看上一篇博客,这是一种创建线程的方式)将需要共享的数据,植入这个Runnable对象里面。例如买票系统,余票是需要共享的,不过在这样做的时候,我想还应该加上synchronized关键字修饰!

    2,多个线程执行的代码不一样

    在这种情况下,就两种思路可以实现(这里参考张孝祥老师的观点)

    其一:将共享数据封装再另外一个对象中,然后将这个对象逐一传递给各个Runnable对象。每个线程对共享数据的操作方法也分配到那个对象身上去完成,这样容易实现对改数据进行的各个操作的互斥和通信。

    其二:将这些Runnable对象作为某一个类中的内部类,共享数据作为这个外部类中的成员变量,每个线程对共享数据的操作方法也分配给外部类,以便实现对共享数据进行的各个操作的互斥和通信,作为内部类的各个Runnable对象调用外部类的这些方法。

    组合:将共享数据封装再另外一个对象中,每个线程对共享数据的操作方法也分配到那个对象身上去完成,对象作为这个外部类中的成员变量或方法中的局部变量,每个线程的Runnable对象作为外部类中的成员内部类或局部内部类。(示例代码所使用的方法),总之,要同步互斥的几段代码最好是分别放在几个独立的方法中,这些方法再放在同一个类中,这样比较好容易实现它们之间的同步互斥通信

    3,简单粗暴的方式

    在程序中,定义一个static变量


    二、代码示例

    <span style="font-family:KaiTi_GB2312;font-size:18px;">package Angel;
    
    public class MultiThreadShareData {
    
    	private static ShareData1 data1 = new ShareData1();
    	
    	public static void main(String[] args) {
    		ShareData1 data2 = new ShareData1();
    		new Thread(new MyRunnable1(data2)).start();//减
    		new Thread(new MyRunnable2(data2)).start();//加
    		
    		final ShareData1 data1 = new ShareData1();
    		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++;
    			System.out.println(j);
    		}
    		
    		public synchronized void decrement(){
    			j--;
    			System.out.println(j);
    		}
    	}</span>


    三、总结

    实现共享数据,不只有这个方式,还应该有已经封装好的更为方便的方式,下篇博客接着介绍。在说到这个基础知识点的时候,突然想到了另外一个关于多线程的基本点,就是在使用多线程的时候,我们会常用到wait()和sleep()方法,那么这两种方法到底有什么区别呢?先看一下线程的状态图:



    简单说来:sleep()方法是属于Thread类中的。而wait()方法是属于Object类中的。


    sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。在调用sleep()方法的过程中,线程不会释放对象锁。
    当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备,获取对象锁进入运行状态。


  • 相关阅读:
    Linux 内核 MCA 总线
    Linux 内核PC/104 和 PC/104+
    Linux 内核即插即用规范
    Linux 内核硬件资源
    Linux 内核 回顾: ISA
    Linux 内核硬件抽象
    Linux 内核硬件抽象
    Linux 内核PCI 中断
    Linux 内核存取 I/O 和内存空间
    哥们的面试经历
  • 原文地址:https://www.cnblogs.com/hhx626/p/7534631.html
Copyright © 2020-2023  润新知