Java多线程的实现方式二

Lock(锁)
 从JDK 5.0开始,Java提供了更强大的线程同步机制——通过显式定义同步锁对象来实现同步。同步锁使用Lock对象充当。
 java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具。锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象。
 ReentrantLock 类实现了 Lock ,它拥有与 synchronized 相同的并发性和
内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以显式加锁、释放锁
实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import java.util.concurrent.locks.ReentrantLock;
 
class Window implements Runnable{
    private int tic = 10;
    //实例化lock
    private ReentrantLock lock = new ReentrantLock();
    @Override
    public void run() {
        while (true){
            try {
                //调用lock锁定方法
                lock.lock();
                if (tic>0){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+":飘号"+":"+tic);
                    tic--;
                }else {
                    break;
                }
            }finally {
                //3.调用解锁方法
                lock.unlock();
            }
 
        }
 
    }
}
public class LookTest {
    public static void main(String[] args) {
        Window w = new Window();
        Thread t1= new Thread(w);
        Thread t2= new Thread(w);
        Thread t3= new Thread(w);
        t1.start();
        t2.start();
        t3.start();
 
    }
}
 
 
 
测试结果
Thread-0:飘号:10
Thread-0:飘号:9
Thread-0:飘号:8
Thread-0:飘号:7
Thread-1:飘号:6
Thread-1:飘号:5
Thread-1:飘号:4
Thread-1:飘号:3
Thread-2:飘号:2
Thread-2:飘号:1
 
Process finished with exit code 0

  synchronized 与lock的

形同点解决线程安全问题

不同点:synchronized机制在执行完相应的代码块以后,自动的释放同步监视器

                lock需要手动的启动同步,同时结束也需要手动释放监视器

线程通信问题

     

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/**
 * 线程通信的例子
 * wait():一旦线程执行此方法进入阻塞状态,并且释放锁
 * notify(): 一旦执行此方法,就会和唤醒wait的线程,如果多个线程wait,就唤醒优先及高的线程
 * notifyAll():一旦执行此方法,就会唤醒所以被wait的线程
 *说明:1.wait(),notify(),notifyAll()三个方法必须使用在同步代码块,或同步方法中。
 * 2.wait(),notify(),notifyAll()三个方法的调用者必须是同步代码块或同步方法中的同步监视器;
 *   否则java.lang.IllegalMonitorStateException
 *
 */
class Number implements Runnable{
    private int number=1;
    private Object obj = new Object();
 
    @Override
    public void run() {
        while (true){
            synchronized (obj) {
                obj.notify();
                if (number<=10){
                    System.out.println(Thread.currentThread().getName()+":"+number);
                    number++;
                    try {
                        //使得调用此wait()方法的线程进入阻塞状态,并会释放锁
                        obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }else {
                    break;
                }
            }
        }
    }
}
public class CommunicationTest {
    public static void main(String[] args) {
        Number n1 = new Number();
 
        Thread thread1 = new Thread(n1);
        Thread thread2 = new Thread(n1);
        thread1.setName("线程1");
        thread2.setName("线程2");
        thread1.start();
        thread2.start();
      // System.out.println();
    }
}
测试结果
线程1:1
线程2:2
线程1:3
线程2:4
线程1:5
线程2:6
线程1:7
线程2:8
线程1:9
线程2:10
 
Process finished with exit code 0

  sleep()和wait()方法

相同点:线程执行到它们的时候进入阻塞状态

不同点:两个方法声明的位置不同;Thread类中声明seelp(),Object中声明的wait()

             调用的范围不一样,seelp()可以在任何需要的场景下调用,wait()必须使用在同步代码块

             是否释放同步监视器的问题:如果两个方法都使用在同步代码块或者同步方法中,seelp()方法不会释放锁,而wait()会释放锁

   线程通信应用

 

  

 

 

 

 

 

posted @   烟雨楼台,行云流水  阅读(56)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏
历史上的今天:
2020-04-21 kubernetes 之ingress-nginx对象实现代理后端主机并实现ssl回话卸载
点击右上角即可分享
微信分享提示