线程休眠以及同步
- 所谓线程休眠就是给线程加入一个定时器,让线程延迟进入可运行状态,延迟时间到达后在通过抢占进程资源来运行线程操作,具体代码如下:
package chapter09;
public class Java03_Thread { public static void main(String[] args) throws Exception { while (true) { Thread.sleep(1000); System.out.println("main线程执行完毕"); } } }
|
- 下面是常用的同步操作结合线程休眠操作(
synchronized
+wait
+notify/notifyAll
)
下面是一个业务场景,我们去银行办理业务通常是需要拿号排队的,银行9点开门,那么此时我们想要第一个办理业务就需要提前于九点去到银行办理业务,此时业务流程就是: 我先到银行拿号->
银行开门开始叫号->
我办理业务
synchronized
是Java
中的关键字,用于实现线程同步。它可以应用于方法或代码块,确保在同一时间只有一个线程可以访问被synchronized
修饰的代码。
synchronized
的主要作用是解决多线程并发访问共享资源时可能出现的数据不一致或冲突的问题。当多个线程同时访问共享资源时,可能会导致数据竞争和不确定的结果。通过使用synchronized
关键字,我们可以确保在同一时间只有一个线程可以执行被synchronized
修饰的代码,从而避免数据竞争和保证数据的一致性。
package Chapter08;
public class Process_25 { public static void main(String[] args) throws Exception {
Num num = new Num();
User user = new User(num); user.start();
Bank bank = new Bank(num); bank.start();
} }
class Num {
}
class Bank extends Thread { private Num num; public Bank( Num num ) { this.num = num; } public void run() { synchronized (num) { try { Thread.sleep(2000); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("9:00, 开发,开始叫号");
num.notifyAll(); } } }
class User extends Thread {
private Num num; public User( Num num ) { this.num = num; } public void run() {
synchronized ( num ) { System.out.println("我是号码1,银行还没开门,我需要等一会"); try { num.wait(); } catch (InterruptedException e) { throw new RuntimeException(e); }
System.out.println("叫到我的号了,该我办业务了。"); } } }
|
wait
(等待)和sleep
(休眠)的区别
线程的安全问题
- 所谓线程安全问题,站在开发者的角度来看那就是多个线程之间操作同一个数据,导致数据冲突了
package Chapter08;
public class Process_safe { public static void main(String[] args) throws Exception {
User7 user = new User7();
Thread t1 = new Thread(()->{ user.name = "zhangsan"; try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println(user.name); });
Thread t2 = new Thread(()->{ user.name = "lisi"; try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println(user.name); }); t1.start(); t2.start();
System.out.println("main线程执行完毕"); } }
class User7 { public String name; }
|
解决方法:
- 将异步并发转换成同步操作就可以很好的解决线程安全问题,同步操作可以使得代码再执行的过程中确保在同一时间只有一个线程可以访问共享资源。这样可以避免多个线程同时修改共享数据导致的数据不一致问题。