调用Thread类的Start方法
能够让线程启动
调用Start方法将线程从“就绪”0》“运行”
yield方法
能够让线程从“运行”-》“就绪”
原理:调用yield方法的线程,将自己的cpu时间片运行权限交给优先级同级或更高优先级线程持有运行。
使用:
1.有时间片轮询:yield方法不一定有效果,因为cpu轮换的速度很快
2.无时间片轮询:yield就会有用
线程优先级设置方法
Thread类的setPriority方法设置优先级。
优先级:1~10 1:最低 10:最高 默认:5
Thread类提供了一些简单的设置常量值:MIN_PRIORITY、NORM_PRIORITY、MAX_PRIORITY
注意:当无时间片轮询时,优先级才会出现作用
join - 线程插队
方法:
join(): 线程必须等待调用join方法的线程死亡才能继续运行,被插队的线程进入阻塞状态
join(long m):等待m个毫秒数后,调用join方法的线程如果还没死亡则停止插队,被插队的线程恢复就绪状态
join(long m,int nm):支持毫秒和纳秒的设置
join方法
public class MyThread2 implements Runnable{
@Override
public void run() {
for (int i=1;i<=10;i++){
if(Thread.currentThread().getName().equals("A")&& i==5){
MyThread2 temp = new MyThread2();
Thread tb = new Thread(temp);
tb.setName("B");
tb.start();
try {
tb.join();
} catch (InterruptedException e) {
System.err.println("线程B启动异常");
}
}
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
sleep方法-线程睡眠
Thread.sleep(1000);// 在代码处使用一个新线程,阻塞当前正在执行的线程1秒后恢复运行
Thread.currentThread().sleep(1000);// 让当前正在运行的线程阻塞,1秒后恢复运行
synchronized
同步锁(非公平锁)
作用: 能让多个线程同步访问资源,实现线程安全操作
用法:
(1)方法上修饰
1. 非静态方法上修饰:锁是不是同一个对象(是不是同一个资源),就看调用方法的对象是否是同一个
2. 静态方法上修饰:锁定的是类,哪怕是不同对象,只要是属于同一个类,就能实现同步
(2)代码块上修饰
1. 对象锁:this或引用数据类型,看代码块参数中的对象是否是同一个
2. 类锁:通过定义的类的字节码文件对象值控制是否是同一个锁资源
以下内容测试代码
public static void main(String[] args) throws FileNotFoundException {
CxkClass c1 = new CxkClass();//尝试使用同一对象和不同对象切换被多个线程调用
CxkClass c2 = new CxkClass();
//匿名类
new Thread(()->{
c1.fun1();
},"A").start();
//匿名类
new Thread(()->{
c1.fun1();
},"B").start();
}
synchronized-方法上修饰-非静态
public class CxkClass {
public synchronized void fun1() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "--" + "fun1:=>" + i);
}
}
public synchronized void fun2() {
for (int i = 0; i < 10; i++) {
System.out.println("fun2:=>" + i);
}
}
}
synchronized-方法上修饰-静态
public static synchronized void fun1() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "--" + "fun1:=>" + i);
}
}
public static synchronized void fun2() {
for (int i = 0; i < 10; i++) {
System.out.println("fun2:=>" + i);
}
}
synchronized-代码块-对象锁
public class CxkClass {
private final static Object key = new Object();
public void fun1(){
synchronized (key){
// 对象锁
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"--"+"fun1:=>"+i);
}
}
}
public void fun2(){
synchronized (key) {
// 对象锁
for (int i = 0; i < 10; i++) {
System.out.println("fun2:=>" + i);
}
}
}
}
synchronized-代码块-类锁
public class CxkClass {
public void fun1(){
synchronized (this.getClass()){
// 类锁
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"--"+"fun1:=>"+i);
}
}
}
public void fun2(){
synchronized (this.getClass()) {
// 类锁
for (int i = 0; i < 10; i++) {
System.out.println("fun2:=>" + i);
}
}
}
}
匿名线程类
//匿名类
new Thread(){
@Override
public void run() {
super.run();
}
}.start();
new Thread(()->{
},"A").start();
线程通信
wait() - 释放当前锁的资源(释放锁就会进入阻塞)
调用wait的是:锁对象,不是线程对象
notify() notifyAll() - 唤醒一个或所有当前锁中阻塞的线程
notify: 只会唤醒其中一个(随机)
(1)无时间片轮询:notify唤醒的是同级别或更高优先级的线程
notifyAll:唤醒所有阻塞线程,全部唤醒(比较安全)
public static void main(String[] args) throws FileNotFoundException {
CxkClass c1 = new CxkClass();
//CxkClass c2 = new CxkClass();
//匿名类
new Thread(()->{
try {
c1.fun1();
} catch (InterruptedException e) {
System.err.println("线程异常");
}
},"A").start();
new Thread(()->{
try {
c1.fun1();
} catch (InterruptedException e) {
System.err.println("线程异常");
}
},"A1").start();
//匿名类
new Thread(()->{
c1.fun2();
},"B").start();
}
public class CxkClass {
public synchronized void fun1() throws InterruptedException {
for (int i = 0; i < 10; i++) {
if((Thread.currentThread().getName().equals("A")||
Thread.currentThread().getName().equals("A1"))&&
i==5){
this.wait();// 当前线程进入等待状态
}
System.out.println(Thread.currentThread().getName() + "--" + "fun1:=>" + i);
}
}
public synchronized void fun2() {
for (int i = 0; i < 10; i++) {
if(Thread.currentThread().getName().equals("B")&&i==5){
this.notifyAll();// 唤醒当前在同一个类型锁中正在阻塞的线程
}
System.out.println(Thread.currentThread().getName() + "fun2:=>" + i);
}
}
}
重入锁
public class CxkClass {
ReentrantLock lock = new ReentrantLock();//重入锁对象
public void fun1() throws InterruptedException {
lock.lock();//锁定
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "--" + "fun1:=>" + i);
}
lock.unlock();
}
public void fun2() {
lock.lock();//锁定
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "fun2:=>" + i);
}
lock.unlock();
}
}
多线程中集合线程安全问题
Collections.synchronized集合类型方法
List<String> list = new ArrayList<>();
Set<String> set = new HashSet<>();
Map<String,Object> map = new HashMap<>();
//返回一个线程安全的集合
List<String> newList = Collections.synchronizedList(list);
Set<String> strings = Collections.synchronizedSet(set);
Map<String, Object> stringObjectMap = Collections.synchronizedMap(map);