Java多线程共享数据、同步、通信

一、线程共享数据

  a)继承Thread,那么我们可以创建很多个这样的类,但是每个这样的类都是相互不关联的,也就是说我们Thread类中的内容每个创建出来的类都有一份,因此它不适合作为数据共享的线程来操作。同时由于Java继承的唯一性,我们只能继承一个对象。

  b)使用runnable就可以解决唯一性和不能共享的问题(不是说使用runnable就解决了共享问题,只是相对于创建Thread来说,它可以算的上是共享了,为了获得更精确的共享问题,它必须的使用线程同步操作)。实现了runnable接口的类比较适合用作共享数据。

  一个测试例子à证明runnable能实现数据共享,thread不能

  Thread_thread一个继承了Thread的线程

  Thread_runnable是一个时间了runnable的接口,他们在run里面有共同的方法


for(int i=0;i<20;i++){
if(ticket>0){
System.out.println(ticket);
ticket--;
}
}
thread_thread th1=new thread_thread();
thread_thread th2=new thread_thread();
thread_thread th3=new thread_thread();
th1.start();
th2.start();
th3.start();

  输入了三组321321321

  因为创建的是三个对象,每一个对象都拥有自己的一个备份

  将一个runnable作为参数,实例化三个thread对象


thread_runnable ru=new thread_runnable();
Thread th1=new Thread(ru);
Thread th2=new Thread(ru);
Thread th3=new Thread(ru);
th1.start();
th2.start();
th3.start();

  输入了32133

  虽然说着不是完整意义上的数据共享,但是相当于上述打印三组完整的数据来说,它已经实现了数据共享,我们从中也可以看到,我们只创建了一个runnable对象(数据只产生了一份),它由三个Thread调用。

 新建三个runnable对象,分别给每一个thread传递


Thread th1=new Thread(new thread_runnable());
Thread th2=new Thread(new thread_runnable());
Thread th3=new Thread(new thread_runnable());
th1.start();
th2.start();
th3.start();

  打印结果是321321321

  我们可以看到我们产生了三个runnable对象,每一个都有自己的一份使用

  综上所述:只有将一个runnable对象作为参数,传递给thread对象才能实现数据共享。

  注意:当我们创建一个Thread对象,并多次调用start方法的时候,系统是不会给你创建多个Thread线程的,它只会运行那个唯一的Thread一次而已,也就是说你运行了一次start方法之后再调用一个它的start方法是没有意义的(那个Thread没有结束的情况下),系统不会给你多次运行的。

  二、线程同步

  a)线程代码块(在代码中添加Synchronized(对象){})

  i.Synchronized(对象),每个对象都有个标志位,当我们进入synchronized代码块中,系统就让这个对象的标志位变为0,就相当于给这个对象添加上了一把锁,当别的代码运行到这个代码块的时候因为加了锁,所以不能进去,当第一个程序它运行出去之后,系统就会让标志位变为1,相当于解锁。这样别的代码又可以访问了。从而实现同步(安全)操作。

  ii.当我们将我们的标志位对象放在run方法里面定义的时候,我们是不能实现同步的,因为我们每次运行一个线程,都将调用它的run方法,从而每次都会创建一个新的标志位对象,也就是说我们所有的run方法都含有自己的一个标志位对象,因此不能实现加锁的过程。一般都是放在runnable接口中进行定义的。

  b)线程方法(在代码的方法申明中public和void之间添加synchronized)

  i.每次只能有一个线程调用这个同步方法,而且每次这个方法都得运行完,这就是同步代码方法。

  ii.同步方法默认使用的是this来作为标志对象位的,这个this就是我们的当前类。

  c)注意:

  i.当一个同步代码块和一个同步代码方法使用的不是同一个对象作为标志位的时候,它们就不会实现同步,这也就是数,当两个同步代码块不使用同一个对象作为标志位,那他们就不能实现同步。

  ii.调用线程的Start方法的时候,并没有真正的运行这个代码,而只是说这个代码已经准备就绪,有运行的可能。

  三、线程通信

  a)当我们的代码中使用了synchronized(对象)同步代码块的时候,如果我们想实现线程通信,也就是如果我们想使用wait、notify或者notifyall时,我们必须在静态代码块中使用对象.wait()、对象.notify()、对象.notifyAll()来通信,不然的话讲会报Illegal的错误。

  b)Notify是唤醒同一监视器下(相当于同一个标志位对象)的第一个wait线程,而notifyall是唤醒所有的处于同一监视器下的(同一标志位对象)的线程。   

最新内容请见作者的GitHub页:http://qaseven.github.io/

   

时间: 2025-01-30 11:27:17

Java多线程共享数据、同步、通信的相关文章

linux下多线程-linux下 多线程共享数据问题

问题描述 linux下 多线程共享数据问题 环境:linux64位服务器 现有海量文件(按秒级的时间顺序源源不断的来),我需要起多线程读取这些文件,并利用文件内容构建一个比较庞大的数据结构(各种map.list的组合),另外还有一批线程检测这个数据结构某些位置的值并触发具体的任务(当然也可以在构建数据结构的同时进行触发). 问题是: 1.多线程如何并发的构建这个数据结构(结构中的list是需要按照文件到来时间排序的),要对数据结构里面的所有数据都上锁么?上锁上在哪?能不上锁么? 2.如何并行的对

java 多线程 出现数据重复调用问题

问题描述 java 多线程 出现数据重复调用问题 java 多线程 出现数据重复调用问题 用id来判断下是否重复可以啊? 求大神给个实列 解决方案 数据重复原因是多线程环境下未作同步处理导致的,可以参考这篇文章:http://blog.csdn.net/wojiushiwo945you/article/details/42553845 至于解决办法,可以使用通常的内置锁同步,即synchronized同步方法或者代码块.示例可参考:http://blog.csdn.net/wojiushiwo9

java多线程中使用同步那它和单线程有什么区别?

问题描述 如果在多线程中使用同步synchronized比如有100个线程,所有线程都要一个一个的执行,那这和单线程不是一样了吗?并且多线程同步的时候操作系统来回的检查锁的状态倒浪费了性能,我理解的是不是哪里不对啊,请知道的帮解答一下,还有就是关于同步有很多方法,是不是都一回事只要会一种就行啊比如我就知道在run里synchronized(obj)这样 解决方案 解决方案二:它们的目的是相同的,都可以很好控制程序执行流程:多线程是为了提高CPU的利用率,在某个线程高速缓存或者执行等待时,可以通知

Java多线程-线程的同步与锁的问题_java

一.同步问题提出 线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏. 例如:两个线程ThreadA.ThreadB都操作同一个对象Foo对象,并修改Foo对象上的数据. package cn.thread; public class Foo { private int x = 100; public int getX() { return x; } public int fix(int y) { x = x - y; return x; } } package cn.thread

JAVA多线程机制之同步与互斥

一个多线程的程序,两个或者多个线程可能需要访问同一个数据资源.这时就必须考虑数据安全的问题,需要线程互斥或者同步. 线程的互斥 当多个线程需要访问同一资源时,要求在一个时间段内只能允许一个线程来操作共享资源,操作完毕后别的线程才能读取该资源,这叫线程的互斥.我们需要使用synchronized来给共享区域加锁,确保共享资源安全. 如果一个线程调用了某个对象的synchronized方法,它在这个方法运行完之前不会被别的线程打断,这就是线程的同步机制.一般将共享资源放在这个同步方法内部,这样就保证

解决Java多线程并发的计数器问题

问题描述 解决Java多线程并发的计数器问题 3C public class Counter { public static int count = 0; public synchronized static void inc() { count++; } public static void main(String[] args) { //同时启动1000个线程,去进行i++计算,看看实际结果 for (int i = 0; i < 1000; i++) { new Thread(new Ru

Java多线程学习(吐血超详细总结)

  本文主要讲了java中多线程的使用方法.线程同步.线程数据传递.线程状态及相应的一些线程函数用法.概述等.在这之前,首先让我们来了解下在操作系统中进程和线程的区别: 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程.(进程是资源分配的最小单位) 线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小.(线程是cpu调度的最小单位) 线程和进程一样分为五个阶段:创建.就绪.运行.阻塞.终止. 多

Java 多线程学习详细总结_java

目录(?)[-] 一扩展javalangThread类 二实现javalangRunnable接口 三Thread和Runnable的区别 四线程状态转换 五线程调度 六常用函数说明 使用方式 为什么要用join方法 七常见线程名词解释 八线程同步 九线程数据传递      本文主要讲了java中多线程的使用方法.线程同步.线程数据传递.线程状态及相应的一些线程函数用法.概述等. 首先讲一下进程和线程的区别: 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个

java 多线程 session共享

问题描述 java 多线程 session共享 在struts2中,启动新的线程 调用ServletActionContext.getRequest() 报空指针错误 解决方案 这个共享的缓存数据是否进程共享的,是不是只能某个线程私有的地址了 解决方案二: Java 多线程 变量共享java多线程共享全局变量java多线程的共享变量访问控制实例 解决方案三: 由于是并发的,当开启线程A(有session)后,再开启线程B,你得确定线程B开启的时候,此时A线程中已经初始化了session及其中想获