多线程学习
1.同步代码块,同步方法
同步代码块
-
代码块又称为初始化块,属于类中的成员[即是类的一部分],类似于方法,将逻辑语句分装在方法体中,通过{}包围起来。
-
和方法不同,没有方法名,没有返回,没有参数,只有方法体,而且不通过对象或类显示调用,而是加载类时,或创建对象时隐形调用
public class MyThread extends Thread{
static int ticket=0;
static Lock lock=new ReentrantLock();
@Override
public void run(){
while(true){
lock.lock();
try {
if(ticket==50){
break;
}else {
Thread.sleep(100);
ticket++;
System.out.println(Thread.currentThread().getName()+" "+ticket);
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}finally {
lock.unlock();
}
}
}
}
为什么要用同步代码块(好处)
优点:
1.相当于另一种形式的构造器(对构造器的补充机制),可以做初始化的操作。
应用场景:假设在类中多个构造器中有重复语句,可以抽取到初始化代码块中,提高代码的重用性。
2.和设计模式中的"单例设计模型"有关(与static修饰符关联有奇效)。
注意:代码块与构造器的调用规则:代码块的执行是优先于构造器的。
同步方法
public class MyRunnable implements Runnable{
int ticket=0;
public String name;
@Override
public void run(){
/*
1.循环
2.同步代码块(或者同步方法)
3.判断共享数据是否到了末尾,如果到了末尾
4.判断共享数据是否到了末尾,如果没到末尾
*/
while(true){
synchronized (this){
if (method()) break;
}
}
}
private boolean method() {
if(ticket==50){
return true;
}else{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
ticket++;
System.out.println(Thread.currentThread().getName()+" "+ticket);
}
return false;
}
}
2.等待唤醒机制
等待唤醒机制中的方法
等待唤醒机制就是用于解决线程通信的问题的,使用到的3个方法的含义如下:
① wait方法:线程不再活动,不再参与调度,进入wait set中(一个等待的集合中),因此不会浪费CPU资源,也不会去竞争锁,这时的线程状态为WAITING(等待状态)。处于WAITING状态的线程需要等待别的线程的通知(notify),然后才能从wait set中释放出来,重新进入调度队列(ready queue)
② notify方法:通知在wait set中的一个线程释放,等待时间越久的约先释放
③ notifyAll方法:释放所有在wait set中的全部线程
注意:
哪怕只通知了一个处于等待中的线程,被通知的线程也不能立即回复执行,因为它是在判断了是否含有锁对象发现没有后才中断的,所以他需要再次尝试获取锁(这个过程很可能会面临其他线程的竞争),成功后才能在最开始调用wait方法之后的地方恢复执行
package com.lc.test02;
import java.util.concurrent.TimeUnit;
/**
* @author liuchao
* @date 2023/4/8
*/
public class ThreadWaitOne {
/**
* 注意:必须使用同一把锁
*/
static Object lock = new Object();
public static void main(String[] args) {
/**
* 线程1
*/
Thread t1 = new Thread(() -> {
synchronized (lock) {
System.out.println("进入" + Thread.currentThread().getName());
try {
lock.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println(Thread.currentThread().getName() + "被唤醒");
}
}, "t1");
t1.start();
try {
TimeUnit.MILLISECONDS.sleep(200);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
/**
* 线程2
*/
Thread t2 = new Thread(() -> {
synchronized (lock) {
System.out.println("进入" + Thread.currentThread().getName());
lock.notify();
System.out.println("唤醒通知已发");
}
}, "t2");
t2.start();
}
}
原文地址:https://blog.csdn.net/2301_80475191/article/details/137845002
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!