Java多线程 ReentrantLock互斥锁详解

加锁和解锁

我们来看下ReentrantLock的基本用法

ThreadDomain35类

public class ThreadDomain35 {
  private Lock lock = new ReentrantLock();
  public void testMethod()
  {
    try
    {
      lock.lock();
      for (int i = 0; i < 2; i++)
      {
        System.out.println("ThreadName = " + Thread.currentThread().getName() + ", i = " + i);
      }
    }
    finally
    {
      lock.unlock();
    }
  }
}

线程和main方法

public class MyThread35 extends Thread {

  private ThreadDomain35 td;

  public MyThread35(ThreadDomain35 td)
  {
    this.td = td;
  }

  public void run()
  {
    td.testMethod();
  }

  public static void main(String[] args)
  {
    ThreadDomain35 td = new ThreadDomain35();
    MyThread35 mt0 = new MyThread35(td);
    MyThread35 mt1 = new MyThread35(td);
    MyThread35 mt2 = new MyThread35(td);
    mt0.start();
    mt1.start();
    mt2.start();
  }
}

输出结果

ThreadName = Thread-2, i = 0
ThreadName = Thread-2, i = 1
ThreadName = Thread-0, i = 0
ThreadName = Thread-0, i = 1
ThreadName = Thread-1, i = 0
ThreadName = Thread-1, i = 1

一个线程必须执行完才能执行下一个线程,说明ReentrantLock可以加锁。

ReentrantLock持有的对象监视器和synchronized不同

ThreadDomain37类,methodB用synchronized修饰

public class ThreadDomain37 {
  private Lock lock = new ReentrantLock();
  public void methodA()
  {
    try
    {
      lock.lock();
      System.out.println("MethodA begin ThreadName = " + Thread.currentThread().getName());
      Thread.sleep(5000);
      System.out.println("MethodA end ThreadName = " + Thread.currentThread().getName());
    }
    catch (InterruptedException e)
    {
      e.printStackTrace();
    }
    finally
    {
      lock.unlock();
    }
  }
  public synchronized void methodB()
  {
    System.out.println("MethodB begin ThreadName = " + Thread.currentThread().getName());
    System.out.println("MethodB begin ThreadName = " + Thread.currentThread().getName());
  }
}

MyThread37_0类

public class MyThread37_0 extends Thread {
  private ThreadDomain37 td;
  public MyThread37_0(ThreadDomain37 td)
  {
    this.td = td;
  }
  public void run()
  {
    td.methodA();
  }
}

MyThread37_1类

public class MyThread37_1 extends Thread {
  private ThreadDomain37 td;
  public MyThread37_1(ThreadDomain37 td)
  {
    this.td = td;
  }

  public void run()
  {
    td.methodB();
  }
}

MyThread37_main方法

public class MyThread37_main {
  public static void main(String[] args)
  {
    ThreadDomain37 td = new ThreadDomain37();
    MyThread37_0 mt0 = new MyThread37_0(td);
    MyThread37_1 mt1 = new MyThread37_1(td);
    mt0.start();
    mt1.start();
  }
}

运行结果如下

MethodA begin ThreadName = Thread-0
MethodB begin ThreadName = Thread-1
MethodB begin ThreadName = Thread-1
MethodA end ThreadName = Thread-0

加了synchronized依然是异步执行,说明ReentrantLock和synchronized持有的对象监视器不同。ReentrantLock需要手动加锁和释放锁。

Condition

基本用法

synchronized与wait()和nitofy()/notifyAll()方法可以实现等待/唤醒模型,ReentrantLock同样可以,需要借助Condition的await()和signal/signalAll(),await()释放锁。

ThreadDomain38类

public class ThreadDomain38 {
  private Lock lock = new ReentrantLock();
  private Condition condition = lock.newCondition();
  public void await()
  {
    try
    {
      lock.lock();
      System.out.println("await时间为:" + System.currentTimeMillis());
      condition.await();
      System.out.println("await等待结束");
    }
    catch (InterruptedException e)
    {
      e.printStackTrace();
    }
    finally
    {
      lock.unlock();
    }
  }
  public void signal()
  {
    try
    {
      lock.lock();
      System.out.println("signal时间为:" + System.currentTimeMillis());
      condition.signal();
      System.out.println("signal等待结束");
    }
    finally
    {
      lock.unlock();
    }
  }
}

MyThread38类,线程和main方法

public class MyThread38 extends Thread
{
  private ThreadDomain38 td;

  public MyThread38(ThreadDomain38 td)
  {
    this.td = td;
  }
  public void run()
  {
    td.await();
  }
  public static void main(String[] args) throws Exception
  {
    ThreadDomain38 td = new ThreadDomain38();
    MyThread38 mt = new MyThread38(td);
    mt.start();
    Thread.sleep(3000);
    td.signal();
  }
}

运行结果如下

await时间为:1563505465346
signal时间为:1563505468345
signal等待结束
await等待结束

可以看到,ReentrantLock和Condition实现了等待/通知模型。

一个Lock可以创建多个Condition;

notify()唤醒的线程是随机的,signal()可以有选择性地唤醒。

Condition选择 唤醒/等待

现在看一个利用Condition选择等待和唤醒的例子

ThreadDomain47类,定义add和sub方法

public class ThreadDomain47 {
  private final Lock lock = new ReentrantLock();

  private final Condition addCondition = lock.newCondition();

  private final Condition subCondition = lock.newCondition();

  private static int num = 0;
  private List<String> lists = new LinkedList<String>();

  public void add() {
    lock.lock();

    try {
      while(lists.size() == 10) {//当集合已满,则"添加"线程等待
        addCondition.await();
      }

      num++;
      lists.add("add Banana" + num);
      System.out.println("The Lists Size is " + lists.size());
      System.out.println("The Current Thread is " + "增加线程");
      System.out.println("==============================");
      this.subCondition.signal();

    } catch (InterruptedException e) {
      e.printStackTrace();
    } finally {//释放锁
      lock.unlock();
    }
  }
  public void sub() {
    lock.lock();

    try {
      while(lists.size() == 0) {//当集合为空时,"减少"线程等待
        subCondition.await();
      }

      String str = lists.get(0);
      lists.remove(0);
      System.out.println("The Token Banana is [" + str + "]");
      System.out.println("The Current Thread is " + "减少线程");
      System.out.println("==============================");
      num--;
      addCondition.signal();

    } catch (InterruptedException e) {
      e.printStackTrace();
    } finally {
      lock.unlock();
    }
  }
}

MyThread40_0类,增加线程

public class MyThread40_0 implements Runnable {
  private ThreadDomain47 task;
  public MyThread40_0(ThreadDomain47 task) {
    this.task = task;
  }
  @Override
  public void run() {
    task.add();
  }
}

MyThread40_1类,减少线程

public class MyThread40_1 implements Runnable {
  private ThreadDomain47 task;

  public MyThread40_1(ThreadDomain47 task) {
    this.task = task;
  }
  @Override
  public void run() {
    task.sub();
  }
}

main方法,启动线程

public class MyThread40_main {
  public static void main(String[] args) {
    ThreadDomain47 task = new ThreadDomain47();
    Thread t1=new Thread(new MyThread40_0(task));
    Thread t3=new Thread(new MyThread40_0(task));
    Thread t7=new Thread(new MyThread40_0(task));
    Thread t8=new Thread(new MyThread40_0(task));
    Thread t2 = new Thread(new MyThread40_1(task));
    Thread t4 = new Thread(new MyThread40_1(task));
    Thread t5 = new Thread(new MyThread40_1(task));
    Thread t6 = new Thread(new MyThread40_1(task));
    t1.start();
    t2.start();
    t3.start();
    t4.start();
    t5.start();
    t6.start();
    t7.start();
    t8.start();
  }
}

输出结果如下

The Lists Size is 1
The Current Thread is 增加线程
==============================
The Lists Size is 2
The Current Thread is 增加线程
==============================
The Token Banana is [add Banana1]
The Current Thread is 减少线程
==============================
The Token Banana is [add Banana2]
The Current Thread is 减少线程
==============================
The Lists Size is 1
The Current Thread is 增加线程
==============================
The Token Banana is [add Banana1]
The Current Thread is 减少线程
==============================
The Lists Size is 1
The Current Thread is 增加线程
==============================
The Token Banana is [add Banana1]
The Current Thread is 减少线程
==============================

可以看到,lists的数量不会增加太多,也不会减少太多。当集合满,使增加线程等待,唤醒减少线程;当集合空,使减少线程等待,唤醒增加线程。我们用wait()/notify()机制无法实现该效果,这里体现了Condition的强大之处。

ReentrantLock中的方法

公平锁和非公平锁

ReentrantLock可以指定公平锁和非公平锁,公平锁根据线程运行的顺序获取锁,非公平锁则通过抢占获得锁,不按线程运行顺序。synchronized是非公平锁。在ReentrantLock(boolean fair)构造函数传入true/false来指定公平锁/非公平锁。
看个例子

ThreadDomain39类和main方法

public class ThreadDomain39 {
  private Lock lock = new ReentrantLock(true);

  public void testMethod()
  {
    try
    {
      lock.lock();
      System.out.println("ThreadName" + Thread.currentThread().getName() + "获得锁");
    }
    finally
    {
      lock.unlock();
    }
  }

  public static void main(String[] args) throws Exception
  {
    final ThreadDomain39 td = new ThreadDomain39();
    Runnable runnable = new Runnable()
    {
      public void run()
      {
        System.out.println("线程" + Thread.currentThread().getName() + "运行了");
        td.testMethod();
      }
    };
    Thread[] threads = new Thread[5];
    for (int i = 0; i < 5; i++)
      threads[i] = new Thread(runnable);
    for (int i = 0; i < 5; i++)
      threads[i].start();
  }
}

输出结果如下

线程Thread-0运行了
ThreadNameThread-0获得锁
线程Thread-1运行了
线程Thread-2运行了
ThreadNameThread-1获得锁
线程Thread-3运行了
线程Thread-4运行了
ThreadNameThread-2获得锁
ThreadNameThread-3获得锁
ThreadNameThread-4获得锁

可以看到公平锁获得锁的顺序和线程运行的顺序相同。公平锁尽可能地让线程获取锁的顺序和线程运行顺序保持一致,再执行几次,可能不一致。

ReentrantLock构造函数传入false,输出结果如下:

线程Thread-0运行了
线程Thread-2运行了
线程Thread-4运行了
线程Thread-3运行了
ThreadNameThread-0获得锁
线程Thread-1运行了
ThreadNameThread-1获得锁
ThreadNameThread-2获得锁
ThreadNameThread-4获得锁
ThreadNameThread-3获得锁

非公平锁获得锁的顺序和线程运行的顺序不同

getHoldCount()

获取当前线程调用lock()的次数,一般debug使用。

看个例子

public class ThreadDomain40 {
  private ReentrantLock lock = new ReentrantLock();
  public void testMethod1()
  {
    try
    {
      lock.lock();
      System.out.println("testMethod1 getHoldCount = " + lock.getHoldCount());
      testMethod2();
    }
    finally
    {
      lock.unlock();
    }
  }
  public void testMethod2()
  {
    try
    {
      lock.lock();
      System.out.println("testMethod2 getHoldCount = " + lock.getHoldCount());
    }
    finally
    {
      lock.unlock();
    }
  }
  public static void main(String[] args)
  {
    ThreadDomain40 td = new ThreadDomain40();
    td.testMethod1();
  }
}

输出结果如下

testMethod1 getHoldCount = 1
testMethod2 getHoldCount = 2

可以看到,testMethod1()被调用了一次,testMethod2()被调用了两次,ReentrantLock和synchronized一样,锁都是可重入的。

getQueueLength()和isFair()

getQueueLength()获取等待的线程数量,isFair()判断是否是公平锁。

ThreadDomain41类和main方法,Thread.sleep(2000)使第一个线程之后的线程都来不及启动,Thread.sleep(Integer.MAX_VALUE)使线程无法unlock()。

public class ThreadDomain41 {
  public ReentrantLock lock = new ReentrantLock();

  public void testMethod()
  {
    try
    {
      lock.lock();
      System.out.println("ThreadName = " + Thread.currentThread().getName() + "进入方法!");
      System.out.println("是否公平锁?" + lock.isFair());
      Thread.sleep(Integer.MAX_VALUE);
    }
    catch (InterruptedException e)
    {
      e.printStackTrace();
    }
    finally
    {
      lock.unlock();
    }
  }

  public static void main(String[] args) throws InterruptedException
  {
    final ThreadDomain41 td = new ThreadDomain41();
    Runnable runnable = new Runnable()
    {
      public void run()
      {
        td.testMethod();
      }
    };
    Thread[] threads = new Thread[10];
    for (int i = 0; i < 10; i++)
      threads[i] = new Thread(runnable);
    for (int i = 0; i < 10; i++)
      threads[i].start();
    Thread.sleep(2000);
    System.out.println("有" + td.lock.getQueueLength() + "个线程正在等待!");
  }
}

输出结果如下

ThreadName = Thread-1进入方法!
是否公平锁?false
有9个线程正在等待!

ReentrantLock默认是非公平锁,只有一个线程lock(),9个线程在等待。

hasQueuedThread()和hasQueuedThreads()

hasQueuedThread(Thread thread)查询指定线程是否在等待锁,hasQueuedThreads()查询是否有线程在等待锁。
看个例子

ThreadDomain41类和main方法,和上面例子类似,Thread.sleep(Integer.MAX_VALUE); 让线程不释放锁,Thread.sleep(2000);让第一个线程之后的线程都无法启动。

public class ThreadDomain42 extends ReentrantLock {
  public void waitMethod()
  {
    try
    {
      lock();
      Thread.sleep(Integer.MAX_VALUE);
    }
    catch (InterruptedException e)
    {
      e.printStackTrace();
    }
    finally
    {
      unlock();
    }
  }

  public static void main(String[] args) throws InterruptedException
  {
    final ThreadDomain42 td = new ThreadDomain42();
    Runnable runnable = new Runnable()
    {
      public void run()
      {
        td.waitMethod();
      }
    };
    Thread t0 = new Thread(runnable);
    t0.start();
    Thread.sleep(500);
    Thread t1 = new Thread(runnable);
    t1.start();
    Thread.sleep(500);
    Thread t2 = new Thread(runnable);
    t2.start();
    Thread.sleep(500);
    System.out.println("t0 is waiting?" + td.hasQueuedThread(t0));
    System.out.println("t1 is waiting?" + td.hasQueuedThread(t1));
    System.out.println("t2 is waiting?" + td.hasQueuedThread(t2));
    System.out.println("Is any thread waiting?" + td.hasQueuedThreads());
  }
}

输出结果如下

t0 is waiting?false
t1 is waiting?true
t2 is waiting?true
Is any thread waiting?true

t0线程获得了锁,t0没有释放锁,导致t1,t2等待锁。

isHeldByCurrentThread()和isLocked()

isHeldByCurrentThread()判断锁是否由当前线程持有,isLocked()判断锁是否由任意线程持有。
请看示例

ThreadDomain43类和main方法

public class ThreadDomain43 extends ReentrantLock {
  public void testMethod()
  {
    try
    {
      lock();
      System.out.println(Thread.currentThread().getName() + "线程持有了锁!");
      System.out.println(Thread.currentThread().getName() + "线程是否持有锁?" +
          isHeldByCurrentThread());
      System.out.println("是否任意线程持有了锁?" + isLocked());
    } finally
    {
      unlock();
    }
  }
  public void testHoldLock()
  {
    System.out.println(Thread.currentThread().getName() + "线程是否持有锁?" +
        isHeldByCurrentThread());
    System.out.println("是否任意线程持有了锁?" + isLocked());
  }

  public static void main(String[] args)
  {
    final ThreadDomain43 td = new ThreadDomain43();
    Runnable runnable0 = new Runnable()
    {
      public void run()
      {
        td.testMethod();
      }
    };
    Runnable runnable1 = new Runnable()
    {
      public void run()
      {
        td.testHoldLock();
      }
    };
    Thread t0 = new Thread(runnable0);
    Thread t1 = new Thread(runnable1);
    t0.start();
    t1.start();
  }
}

输出结果如下

Thread-0线程持有了锁!
Thread-1线程是否持有锁?false
Thread-0线程是否持有锁?true
是否任意线程持有了锁?true
是否任意线程持有了锁?true

Thread-0线程testMethod方法持有锁,Thread-1线程testHoldLock方法没有lock操作,所以不持有锁。

tryLock()和tryLock(long timeout, TimeUnit unit)

tryLock()有加锁的功能,获得了锁且锁没有被另外一个线程持有,此时返回true,否则返回false,可以有效避免死锁。tryLock(long timeout, TimeUnit unit)表示在给定的时间内获得了锁,锁没有被其他线程持有,且不处于中断状态。返回true,否则返回false;

看个例子

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

    System.out.println("开始");
    final Lock lock = new ReentrantLock();
    new Thread() {
      @Override
      public void run() {
        String tName = Thread.currentThread().getName();
        if (lock.tryLock()) {
          System.out.println(tName + "获取到锁!");
        } else {
          System.out.println(tName + "获取不到锁!");
          return;
        }
        try {
          for (int i = 0; i < 5; i++) {
            System.out.println(tName + ":" + i);
          }
          Thread.sleep(5000);
        } catch (Exception e) {
          System.out.println(tName + "出错了!");
        } finally {
          System.out.println(tName + "释放锁!");
          lock.unlock();
        }

      }
    }.start();

    new Thread() {
      @Override
      public void run() {
        String tName = Thread.currentThread().getName();

        try {
          if (lock.tryLock(1,TimeUnit.SECONDS)) {
            System.out.println(tName + "获取到锁!");
          } else {
            System.out.println(tName + "获取不到锁!");
            return;
          }
        } catch (InterruptedException e) {
          e.printStackTrace();
        }

        try {
          for (int i = 0; i < 5; i++) {
            System.out.println(tName + ":" + i);
          }

        } catch (Exception e) {
          System.out.println(tName + "出错");
        } finally {
          System.out.println(tName + "释放锁!");
          lock.unlock();
        }
      }
    }.start();

    System.out.println("结束");
  }
}

输出结果如下

开始
Thread-0获取到锁!
Thread-0:0
Thread-0:1
Thread-0:2
Thread-0:3
Thread-0:4
结束
Thread-1获取不到锁!
Thread-0释放锁!

Thread-0先获得了锁,且sleep了5秒,导致Thread-1获取不到锁,我们给Thread-1的tryLock设置1秒,一秒内获取不到锁就会返回false。

如果Thread.sleep(0),那么Thread-0和Thread-1都可以获得锁,园友可以自己试下。

synchronized和ReentrantLock的比较

1.synchronized关键字是语法层面的实现,ReentrantLock要手动lock()和unlock();

2.synchronized是不公平锁,ReentrantLock可以指定是公平锁还是非公平锁;

3.synchronized等待/唤醒机制是随机的,ReentrantLock借助Condition的等待/唤醒机制可以自行选择等待/唤醒;

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 详解java中的互斥锁信号量和多线程等待机制

    互斥锁和信号量都是操作系统中为并发编程设计基本概念,互斥锁和信号量的概念上的不同在于,对于同一个资源,互斥锁只有0和1 的概念,而信号量不止于此.也就是说,信号量可以使资源同时被多个线程访问,而互斥锁同时只能被一个线程访问 互斥锁在java中的实现就是 ReetranLock , 在访问一个同步资源时,它的对象需要通过方法 tryLock() 获得这个锁,如果失败,返回 false,成功返回true.根据返回的信息来判断是否要访问这个被同步的资源.看下面的例子 public class Reen

  • 详解Java多线程编程中互斥锁ReentrantLock类的用法

    0.关于互斥锁 所谓互斥锁, 指的是一次最多只能有一个线程持有的锁. 在jdk1.5之前, 我们通常使用synchronized机制控制多个线程对共享资源的访问. 而现在, Lock提供了比synchronized机制更广泛的锁定操作, Lock和synchronized机制的主要区别: synchronized机制提供了对与每个对象相关的隐式监视器锁的访问, 并强制所有锁获取和释放均要出现在一个块结构中, 当获取了多个锁时, 它们必须以相反的顺序释放. synchronized机制对锁的释放是

  • Java多线程并发编程(互斥锁Reentrant Lock)

    Java 中的锁通常分为两种: 通过关键字 synchronized 获取的锁,我们称为同步锁,上一篇有介绍到:Java 多线程并发编程 Synchronized 关键字. java.util.concurrent(JUC)包里的锁,如通过继承接口 Lock 而实现的 ReentrantLock(互斥锁),继承 ReadWriteLock 实现的 ReentrantReadWriteLock(读写锁). 本篇主要介绍 ReentrantLock(互斥锁). ReentrantLock(互斥锁)

  • Java concurrency之互斥锁_动力节点Java学院整理

    ReentrantLock介绍 ReentrantLock是一个可重入的互斥锁,又被称为"独占锁". 顾名思义,ReentrantLock锁在同一个时间点只能被一个线程锁持有:而可重入的意思是,ReentrantLock锁,可以被单个线程多次获取. ReentrantLock分为"公平锁"和"非公平锁".它们的区别体现在获取锁的机制上是否公平."锁"是为了保护竞争资源,防止多个线程同时操作线程而出错,ReentrantLock

  • Java互斥锁简单实例

    本文实例讲述了Java互斥锁.分享给大家供大家参考.具体分析如下: 互斥锁,常常用于多个线程访问独占式资源,比如多个线程同时写一个文件,虽然互斥访问方式不够高效,但是对于一些应用场景却很有意义 //没有互斥锁的情况(可以自己跑跑看运行结果): public class LockDemo { // private static Object lock = new Object(); // static确保只有一把锁 private int i = 0; public void increaseI(

  • Java多线程 ReentrantLock互斥锁详解

    加锁和解锁 我们来看下ReentrantLock的基本用法 ThreadDomain35类 public class ThreadDomain35 { private Lock lock = new ReentrantLock(); public void testMethod() { try { lock.lock(); for (int i = 0; i < 2; i++) { System.out.println("ThreadName = " + Thread.curre

  • Java多线程用法的实例详解

    Java多线程用法的实例详解 前言: 最全面的java多线程用法解析,如果你对Java的多线程机制并没有深入的研究,那么本文可以帮助你更透彻地理解Java多线程的原理以及使用方法. 1.创建线程 在Java中创建线程有两种方法:使用Thread类和使用Runnable接口.在使用Runnable接口时需要建立一个Thread实例.因此,无论是通过Thread类还是Runnable接口建立线程,都必须建立Thread类或它的子类的实例.Thread构造函数: public Thread( ); p

  • Java多线程 线程状态原理详解

    这篇文章主要介绍了Java多线程 线程状态原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 java.lang.Thread.State枚举定义了6种线程状态. NEW: 尚未启动(start)的线程的线程状态 RUNNABLE: 运行状态,但线程可能正在JVM中执行,也可能在等待CPU调度 BLOCKED: 线程阻塞,等待监视器锁以进入同步代码块/方法 WAITING: 等待状态.使用以下不带超时的方式时会进入:Object.wait.

  • java多线程JUC常用辅助类详解

    1.countDownLatch 减法计数器:实现调用几次线程后,在触发另一个任务 简单代码实现: 举例说明:就像五个人在同一房间里,有一个看门的大爷,当五个人都出去后,他才能锁门,也就是说 执行5次出门这个动作的线程后,才出发了锁门的这个动作 import java.util.concurrent.CountDownLatch; /** * @program: juc * @description * @author: 不会编程的派大星 * @create: 2021-04-24 16:55

  • Java多线程案例之定时器详解

    目录 一.什么是定时器 二.标准库中的定时器(timer) 2.1什么是定时器 2.2定时器的使用 三.实现定时器 3.1什么是定时器 3.2最终实现代码 一.什么是定时器 定时器也是软件开发中的一个重要组件. 类似于一个 “闹钟”. 达到一个设定的时间之后, 就执行某个指定好的代码 定时器是一种实际开发中非常常用的组件,我们举几个例子: 1.比如网络通信中, 如果对方 500ms 内没有返回数据, 则断开连接尝试重连 2.比如一个 Map, 希望里面的某个 key 在 3s 之后过期(自动删除

  • Java多线程通信实现方式详解

    这篇文章主要介绍了Java多线程通信实现方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 线程通信的方式: 1.共享变量 线程间通信可以通过发送信号,发送信号的一个简单方式是在共享对象的变量里设置信号值.线程A在一个同步块里设置boolean型成员变量hasDataToProcess为true,线程B也在同步代码块里读取hasDataToProcess这个成员变量.这个简单的例子使用了一个持有信号的对象,并提供了set和get方法. pu

  • Java多线程编程综合案例详解

    目录 Java多线程综合案例 数字加减 生产电脑 竞争抢答 Java多线程综合案例 数字加减 设计4个线程对象,两个线程执行减操作,两个线程执行加操作 public class ThreadDemo{ public static void main(String[] args) throws Exception { Resource res=new Resource(); AddThread at=new AddThread(res); SubThread st=new SubThread(re

  • Java多线程解决龟兔赛跑问题详解

    目录 多线程4(龟兔赛跑-休眠线程) 1.题目 2.解题思路 3.代码详解 多线程4(龟兔赛跑-休眠线程) 1.题目 在龟兔赛跑中,领先的兔子因为通宵写博客,中途太累睡着了,跑输了乌龟.这个故事说明了兔子是爱学习的同学.咳咳,通宵是不可取的,大家别学. 实现:使用线程休眠模拟龟兔赛跑比赛 2.解题思路 创建一个类:RaceFrame,继承了JFrame.用来界面显示两个文本区域,用来输出乌龟和兔子的比赛记录,比赛开始按钮用来开始比赛. 编写内部类:Rabbit,该类实现了Runnable接口,在

  • JAVA多线程之方法 JOIN详解及实例代码

    JAVA多线程 JOIN 对于Java开发人员,多线程应该是必须熟练应用的知识点,特别是开发基于Java语言的产品.本文将深入浅出的表述Java多线程的知识点,在后续的系列里将侧重于Java5由Doug Lea教授提供的Concurrent并行包的设计思想以及具体实现与应用. 如何才能深入浅出呢,我的理解是带着问题,而不是泛泛的看.所以该系列基本以解决问题为主,当然我也非常希望读者能够提出更好的解决问题的方案以及提出更多的问题.由于水平有限,如果有什么错误之处,请大家提出,共同讨论,总之,我希望

  • java多线程中线程封闭详解

    线程封闭的概念 访问共享变量时,通常要使用同步,所以避免使用同步的方法就是减少共享数据的使用,这种技术就是线程封闭. 实现线程封闭的方法 1:ad-hoc线程封闭 这是完全靠实现者控制的线程封闭,他的线程封闭完全靠实现者实现.也是最糟糕的一种线程封闭.所以我们直接把他忽略掉吧. 2:栈封闭 栈封闭是我们编程当中遇到的最多的线程封闭.什么是栈封闭呢?简单的说就是局部变量.多个线程访问一个方法,此方法中的局部变量都会被拷贝一分儿到线程栈中.所以局部变量是不被多个线程所共享的,也就不会出现并发问题.所

随机推荐