Java高级特性之多线程,java实战项目视频

}

System.out.println(Thread.currentThread().getName() + “:卖票,票号为:” + ticket);

ticket–;

}

}

}

3.4 利用Runnable实现线程同步(Lock锁)

3.4.1 Lock锁定义

  • 从 JDK 5.0开始,Java 提供了更强大的线程同步机制 通过显式定义同步锁对象来实现同步,同步锁使用 Lock 对象充当 。

  • java.util.concurrent.locks.Lock 接口是控制多个线程对共享资源进行访问的工具。 锁提供了对共享资源的独占访问,每次只能有一个线程对 Lock 对象加锁,线程开始访问共享资源之前应先获得 Lock 对象 。

  • ReentrantLock 类实现了 Lock ,它拥有与 synchronized 相同的并发性和内存语义, 在 实现线程安全的控制中,比较常用的是 ReentrantLock 可以显式加锁、释放锁。

3.4.2 代码实例

import java.util.concurrent.locks.ReentrantLock;

/**

  • 解决线程安全问题的方式三:Lock锁 — JDK5.0新增

    1. 面试题:synchronized 与 Lock的异同?
  • 相同:二者都可以解决线程安全问题

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

  • Lock需要手动的启动同步(lock()),同时结束同步也需要手动的实现(unlock())
  • 2.优先使用顺序:

  • Lock  同步代码块(已经进入了方法体,分配了相应资源)  同步方法(在方法体之外)

*/

public class Lock {

public static void main(String[] args) {

Window3 w = new Window3();

Thread t1 = new Thread(w);

Thread t2 = new Thread(w);

Thread t3 = new Thread(w);

t1.setName(“窗口1”);

t2.setName(“窗口2”);

t3.setName(“窗口3”);

t1.start();

t2.start();

t3.start();

}

}

class Window3 implements Runnable{

private int ticket = 100;

//1.实例化ReentrantLock

private ReentrantLock lock = new ReentrantLock();

@Override

public void run() {

while(true){

try{//2.调用锁定方法lock()

lock.lock();

if(ticket > 0){

try {

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName() + “:售票,票号为:” + ticket);

ticket–;

}else{

break;

}

}finally {

//3.调用解锁方法:unlock()

lock.unlock();

}

}

}

}

3.5 synchronized同步与Lock锁的区别

相同点:二者都可以解决线程安全问题。

不同点:

  • synchronized机制在执行完相应的同步代码以后,自动的释放同步监视器,Lock 是显式锁(需要手动开启和关闭锁), synchronized 是隐式锁,出了作用域自动释放;

  • Lock 只有代码块锁, synchronized 有代码块锁和方法锁;

  • 使用 Lock 锁, JVM 将花费较少的时间来调度线程,性能更好,并且具有更好的扩展性(提供更多的子类)。

使用的优先顺序:Lock锁、synchronized同步代码块、synchronized同步方法。

同步虽然解决了线程的安全问题,但其实操作同步代码时,只能一个线程参与,其他线程等待。相当于是一个单线程的过程,效率低。

3.6 死锁问题

3.6.1 定义

不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁。

  • 出现死锁后,不会出现异常,不会出现提示,只是所的线程都处于阻塞状态,无法继续

  • 我们使用同步时,要避免出现死锁。

3.6.2 解决办法

  1. 专门的算法、原则

  2. 尽量减少同步资源的定义

  3. 尽量避免嵌套同步

3.6.3 死锁的实例

//死锁的演示;死锁的增强版

class A {

public synchronized void foo(B b) { //同步监视器:A类的对象:a

System.out.println("当前线程名: " + Thread.currentThread().getName()

  • " 进入了A实例的foo方法"); //

System.out.println("当前线程名: " + Thread.currentThread().getName()

  • " 企图调用B实例的last方法"); // ③

b.last();

}

public synchronized void last() {//同步监视器:A类的对象:a

System.out.println(“进入了A类的last方法内部”);

}

}

class B {

public synchronized void bar(A a) {//同步监视器:b

System.out.println("当前线程名: " + Thread.currentThread().getName()

  • " 进入了B实例的bar方法"); // ②

System.out.println("当前线程名: " + Thread.currentThread().getName()

  • " 企图调用A实例的last方法"); // ④

a.last();

}

public synchronized void last() {//同步监视器:b

System.out.println(“进入了B类的last方法内部”);

}

}

public class DeadLock implements Runnable {

A a = new A();

B b = new B();

public void init() {

Thread.currentThread().setName(“主线程”);

// 调用a对象的foo方法

a.foo(b);

System.out.println(“进入了主线程之后”);

}

@Override

public void run() {

Thread.currentThread().setName(“副线程”);

// 调用b对象的bar方法

b.bar(a);

System.out.println(“进入了副线程之后”);

}

public static void main(String[] args) {

DeadLock dl = new DeadLock();

new Thread(dl).start();

dl.init();

}

}

4 继承Thread类

=======================

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值