java非常规线程同步问题一个!

问题描述

我现在有一个这样的资源类,可能的方法如下所示class A {List test;set(); // 初始化test,并赋值reset(); // 请空test,并对test重新赋值get(int index); // 取test中的某个值}一般情况下test初始化后有多个线程会调用get()方法取值,为了保证效率也不需要同步get()方法,但一定概率下会有其他线程对test调用reset()方法,我的需求是:当有线程调用reset()方法时(同一时刻只有一个线程调用reset()),其他线程再调用get()时,必须等待reset()结束后,方可继续。主要是避免读取错误!我想请问一下大家谁有比较好的解决方案? 问题补充:由于我的系统在绝大多数情况下都是在(多个线程)调用get()方法,如果对get()同步,效率将大大降低,可能不符合要求!非常感谢您的回答,以下是我在您提供的方案上修改后做的测试代码!package test;import java.util.ArrayList;import java.util.List;import java.util.Random;public class TestSync {private List<String> lists = new ArrayList<String>();public TestSync() {lists.add("张三");lists.add("李四");lists.add("张三");lists.add("李四");lists.add("张三");lists.add("李四");lists.add("张三");lists.add("李四");lists.add("张三");lists.add("李四");lists.add("张三");lists.add("李四");lists.add("张三");lists.add("李四");}public void reset() {synchronized (this) {System.out.println(Thread.currentThread().getName() + "正在执行reset()");lists.clear();try {Thread.sleep(5000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}lists.add("张三");lists.add("李四");lists.add("张三");lists.add("李四");lists.add("张三");lists.add("李四");lists.add("张三");lists.add("李四");lists.add("张三");lists.add("李四");lists.add("张三");lists.add("李四");lists.add("张三");lists.add("李四");lists.add("张三");lists.add("李四");lists.add("张三");lists.add("李四");System.out.println(Thread.currentThread().getName() + "reset()执行完毕");}}public synchronized String get(int i) {System.out.println(Thread.currentThread().getName() + "执行get(int i)");try {Thread.sleep(2000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}return lists.get(i);}}class TestThread extends Thread {private TestSync a = null;public TestThread(TestSync a) {this.a = a;}@Overridepublic void run() {// TODO Auto-generated method stubint loop = 20;while (loop > 0) {loop--;a.get((new Random()).nextInt(6));if ((int) (Math.random() * 10) == 1) {a.reset();} else {a.get((new Random()).nextInt(14));}}}}

解决方案

为什么呢?下面是我机器上的执行结果Thread-0执行get(int i)Thread-0执行get(int i)Thread-1执行get(int i)Thread-0正在执行reset()Thread-0reset()执行完毕Thread-1执行get(int i)Thread-1执行get(int i)Thread-1执行get(int i)Thread-1执行get(int i)Thread-1执行get(int i)Thread-1正在执行reset()Thread-1reset()执行完毕Thread-1执行get(int i)Thread-0执行get(int i)Thread-0执行get(int i)Thread-0执行get(int i)Thread-0执行get(int i)Thread-0执行get(int i)Thread-0执行get(int i)Thread-0执行get(int i)Thread-0执行get(int i)Thread-0执行get(int i)Thread-0执行get(int i)Thread-0执行get(int i)Thread-0执行get(int i)Thread-0执行get(int i)Thread-0执行get(int i)Thread-0执行get(int i)Thread-0执行get(int i)Thread-0执行get(int i)Thread-1执行get(int i)Thread-1执行get(int i)Thread-1执行get(int i)Thread-1正在执行reset()Thread-1reset()执行完毕Thread-1执行get(int i)Thread-1执行get(int i)Thread-1执行get(int i)Thread-1执行get(int i)Thread-1执行get(int i)Thread-1执行get(int i)Thread-1执行get(int i)Thread-1执行get(int i)分析一下上面的结果:Thread-1正在执行reset()Thread-1reset()执行完毕之间没有任何的get(int i)操作,可是在reset()方法中,线程要sleep(5000),这么长的时间,其他的线程都没有执行get(int i)操作,这不是你的要求吗?你也可以把sleep的时间设置成更长的时间,在reset方法执行完之前,其他的线程是不能get方法的
解决方案二:
只要简单的在reset()方法中加入以下代码:reset(){synchronized(this){ // 这里添加功能 // 请空test,并对test重新赋值 }}下面的代码为验证想法的一个代码import java.util.ArrayList;import java.util.List;class A {private List<String> lists = new ArrayList<String>();public A() {lists.add("张三");lists.add("李四");}public void reset() {synchronized (this) {System.out.println(Thread.currentThread().getName() + "正在执行reset()");try {Thread.sleep(5000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}lists.clear();lists.add("张三");lists.add("李四");System.out.println(Thread.currentThread().getName() + "reset()执行完毕");}}public synchronized String get(int i) {System.out.println(Thread.currentThread().getName() + "执行get(int i)");return lists.get(i);}}class TestThread extends Thread {private A a = null;public TestThread(A a) {this.a = a;}@Overridepublic void run() {// TODO Auto-generated method stubint loop = 20;while (loop > 0) {loop--;if ((int) (Math.random() * 10) == 1) {a.reset();} else {a.get(1);}}}}public class T1 {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubA a = new A();TestThread t1 = new TestThread(a);TestThread t2 = new TestThread(a);TestThread t3 = new TestThread(a);TestThread t4 = new TestThread(a);t1.start();t2.start();// t3.start();// t4.start();}}
解决方案三:
import java.util.List;class Test1 {List test; boolean isLocked =false;void set() {}synchronized void reset() {isLocked = true;System.out.println("start this is reset");try {Thread.sleep(300);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}/*****/System.out.println("end this is reset");isLocked = false;}int get(int index) { //这里等待reset()执行完。while (isLocked) {System.out.println("00000000000");}return index;}public static void main(String[] args) {final Test1 t = new Test1();new Thread(new Runnable(){public void run(){t.reset();}}).start();new Thread(new Runnable(){public void run(){System.out.println("ssssssssss:"+t.get(0));}}).start();}}

时间: 2024-11-09 02:17:21

java非常规线程同步问题一个!的相关文章

java关于线程同步的问题

问题描述 java关于线程同步的问题 package 线程.TestTeread_5; /* push和pop增加减少数组元素, 我的问题是: 为什么去掉push和pop的synchronized修饰关键词时,会报如下错误 异常: Exception in thread "Thread-0" java.lang.IllegalMonitorStateException at java.lang.Object.notify(Native Method) at 线程.TestTeread_

java中线程同步,线程让步,线程休眠的区别和联系是什么

问题描述 java中线程同步,线程让步,线程休眠的区别和联系是什么 java中线程同步,线程让步,线程休眠的区别和联系是什么 线程的本质还是一个运行中的类, 解决方案 线程同步:是保证多线程安全访问竞争资源的一种手段,java中常用的是加锁机制即synchronized同步代码块实现的. 线程让步的方法是yield(),休眠方法是sleep().sleep()方法和yield()方法都是Thread类的静态方法,都会使当前处于运行状态的线程放弃CPU,把运行机会让给别的线程. 两者的区别在于:s

线程同步的一个问题,求高手指导

问题描述 线程同步的一个问题,求高手指导 public class TestTicket{ public static void main(String[] args){ SellTickets st = new SellTickets(); Thread t1 = new Thread(st,"窗口1--"); Thread t2 = new Thread(st,"窗口2--"); Thread t3 = new Thread(st,"窗口3--&quo

深入解析Java的线程同步以及线程间通信_java

Java线程同步 当两个或两个以上的线程需要共享资源,它们需要某种方法来确定资源在某一刻仅被一个线程占用.达到此目的的过程叫做同步(synchronization).像你所看到的,Java为此提供了独特的,语言水平上的支持. 同步的关键是管程(也叫信号量semaphore)的概念.管程是一个互斥独占锁定的对象,或称互斥体(mutex).在给定的时间,仅有一个线程可以获得管程.当一个线程需要锁定,它必须进入管程.所有其他的试图进入已经锁定的管程的线程必须挂起直到第一个线程退出管程.这些其他的线程被

详解Java传统线程同步通信技术

编写代码实现以下功能 子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着再回到主线程又循环100次,如此循环50次. 分析 1)子线程循环10次与主线程循环100次必须是互斥的执行,不能出现交叉,下面代码中通过synchronized关键字实现此要求: 2)子线程与主线程必须交替出现,可以通过线程同步通信技术实现,下面代码中通过bShouldSub变量实现此要求: 其他需要注意的地方 1)其中business变量必须声明为final类型,因为在匿名内部类和局部内部类中调用

java 使用线程做的一个简单的ATM存取款实例代码_java

实现Runnable接口.当一个线程已继承了另一个类时,就只能用实现Runnable接口的方法来创建线程,且便于保持程序风格的一致性. 我们知道,一个具有生命的线程,具有下面五种状态: 创建状态 使用new运算符创建一个线程后,该线程仅仅是一个空对象,系统没有分配资源,称该线程处于创建状态(new thread) 可运行状态 使用start()方法启动一个线程后,系统为该线程分配了除CPU外的所需资源,使该线程处于可运行状态(Runnable) 运行中状态 Java运行系统通过调度选中一个Run

java 实现线程同步的方式有哪些_java

什么是线程同步? 当使用多个线程来访问同一个数据时,非常容易出现线程安全问题(比如多个线程都在操作同一数据导致数据不一致),所以我们用同步机制来解决这些问题. 实现同步机制有两个方法: 1.同步代码块: synchronized(同一个数据){} 同一个数据:就是N条线程同时访问一个数据. 2. 同步方法: public synchronized 数据返回类型 方法名(){} 就是使用 synchronized 来修饰某个方法,则该方法称为同步方法.对于同步方法而言,无需显示指定同步监视器,同步

java web-多线程同步银行多账户取钱

问题描述 多线程同步银行多账户取钱 最近一直在想一个多线程的问题,举个例子 比如javaweb银行项目,同时两个人在异地个存取200元如何保证不出差错. 两个人在异地同时登陆的话其实在系统中是属于两个数据相同的对象(spring+hibernate)如果使用对象的排它锁也不会起作用.这种需求应该怎样实现那? 解决方案 跪求大神答疑解惑~~~~(>_<)~~~~

java线程同步 死锁问题

问题描述 java线程同步 死锁问题 写了一个java中线程同步的死锁问题,但是输出结果就是不对,劳烦前辈指点指点.源代码如下: public class TestDeadLock implements Runnable{ public static int flag = 1; static Object o1 = new Object(); static Object o2 = new Object(); public void run(){ System.out.println(""