注: syso会严重影响多线程,具体可查看:https://blog.csdn.net/w05980598/article/details/79933693
1. 为什么使用线程:
使用线程充分利用计算机的cpu资源提高效率
阻塞代码避免应先其他代码执行,方法线程中,并行执行
2. 创建线程
- 继承Thread
继承Thread,编写线程子类
重写run()方法,在run()方法中添加线程中并行执行的代码
- 实现Runable
定义Runable接口子类
实现run()方法
新建Thread对象时,把Runnable对象交给线程对象
线程对象启动后,执行Runnable对象的run()方法
3.线程的方法
Thread.currentThread() 获取正在执行的线程对象
Thread.sleep(long t) 正在执行的线程,暂停指定的毫秒时长
setName()
getName()
start() 启动线程
interrupt() 打断一个线程的暂停状态
join() 在当前线程中,等待被调用线程结束
getPriority() 线程的优先级,1-10,默认为5
setPriority(p) 线程的优先级,1-10,默认为5
setDaemon(true) 把线程设置成后台线程、守护线程,所有的前台线程结束,虚拟机就会自动关闭,不会等待后台线程。
4.线程生命周期
5. 线程共享数据冲突
一个线程修改数据,另一个线程访问到了被修改了一半的数据
6. 线程同步
一个线程访问数据时,其他线程要等待
JAVA中所有的对象,都有一个同步锁
让多个线程争夺同一个对象的同步锁,谁抢到谁执行,得不到锁就等待。
1.同步代码块
synchronized(争夺的对象){
数据访问代码
}
2.同步方法
//非静态方法,争夺的是当前对象的锁
synchronized void f(){ }
//静态方法,争夺“类对象”的锁
static synchronized void f(){ }
案例:
package com.demo; import java.security.GeneralSecurityException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Scanner; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadDemo4 { public static void main(String[] args) { Test5 test5 = new Test5(); Test5 test6 = new Test5(); Thread t5 = new Thread(test5); Thread t6 = new Thread(test6); t5.start(); while (true) { int i = test5.getI(); System.out.println(i); if(i%2==1){ System.out.println("iiiii : "+i); //退出虚拟机 System.exit(0); } } } static class Test5 implements Runnable{ static int i=0; //i ++ public synchronized void add() { i++; i++; } //获取i的值 public synchronized int getI(){ return i; } @Override public void run() { while (true){ add(); } } } }
7. 等待和通知
Object 的方法
wait()
线程在被调用的对象上等待
notify()
通知在对象上等待的一个线程
notifyAll()
通知在对象上等待的所有的线程
注:
必须在synchronized 代码块内调用
必须在加锁的对象上等待、通知
wait()外面应该使用while(){} 循环条件进行检查
8.同步监视器
执行到synchronized,会在加锁的对象上,关联一个同步监视器。