目录
一、线程生命周期
1.线程六大状态
JDK中用线程的枚举表示了线程的集中状态。
- public static enum Thread.State extends Enum<Thread.State>线程状态。线程可以处于以下状态之一:一个线程可以在给定时间点处于一个状态。这些状态是不反映任何操作系统线程状态的虚拟机状态。
-
- NEW尚未启动的线程处于此状态。
- RUNNABLE在Java虚拟机中执行的线程处于此状态。
- BLOCKED被阻塞等待监视器锁定的线程处于此状态。
- WAITING正在等待另一个线程执行特定动作的线程处于此状态。
- TIMED_WAITING正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。
- TERMINATED已退出的线程处于此状态。
一个线程可以在给定时间点处于一个状态。这些状态是不反映任何操作系统线程状态的虚拟机状态。
2.线程状态转换图
/**
* @author: 程序员飞扬
* @公众hao:程序员飞扬
* @description:
*/
public class ThreadState_ {
public static void main(String[] args) throws InterruptedException {
T0 t0 = new T0();
System.out.println(t0.getName() + "状态:" + t0.getState());
t0.start();
while(Thread.State.TERMINATED != t0.getState()){
System.out.println(t0.getName() + "状态:" + t0.getState());
Thread.sleep(1000);
}
System.out.println(t0.getName() + "状态:" + t0.getState());
}
}
class T0 extends Thread{
@Override
public void run() {
while(true){
for (int i = 1; i <= 5; i++) {
System.out.println("hi" + i + "状态:" + Thread.currentThread().getState());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
}
}
}
输出:
Thread-0状态:NEW
Thread-0状态:RUNNABLE
hi1状态:RUNNABLE
Thread-0状态:RUNNABLE
hi2状态:RUNNABLE
Thread-0状态:RUNNABLE
hi3状态:RUNNABLE
Thread-0状态:RUNNABLE
hi4状态:RUNNABLE
Thread-0状态:RUNNABLE
hi5状态:RUNNABLE
Thread-0状态:RUNNABLE
Thread-0状态:TERMINATED
二、线程同步
1.同步介绍
2.同步方法
3.案例(模拟三个线程同时售票)
/**
* @author:程序员飞扬
* @公众hao:程序员飞扬
* @description:
*/
public class SellTicket {
public static void main(String[] args) {
Sell sell = new Sell();
new Thread(sell).start();
new Thread(sell).start();
new Thread(sell).start();
}
}
class Sell implements Runnable{
static int ticket = 10;
private boolean loop = true;
public synchronized void m(){
if(ticket <= 0){
setLoop(false);
System.out.println("没票了,售票结束");
return;
}
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("窗口" + Thread.currentThread().getName()+"卖出了一张票,剩余" + (--ticket) );
}
@Override
public void run() {
while(loop){
m();
}
}
public void setLoop(boolean loop) {
this.loop = loop;
}
}
输出:
窗口Thread-0卖出了一张票,剩余9
窗口Thread-0卖出了一张票,剩余8
窗口Thread-0卖出了一张票,剩余7
窗口Thread-0卖出了一张票,剩余6
窗口Thread-0卖出了一张票,剩余5
窗口Thread-0卖出了一张票,剩余4
窗口Thread-0卖出了一张票,剩余3
窗口Thread-0卖出了一张票,剩余2
窗口Thread-0卖出了一张票,剩余1
窗口Thread-0卖出了一张票,剩余0
没票了,售票结束
没票了,售票结束
没票了,售票结束
4.同步原理
5.同步注意事项
/**
* @author:程序员飞扬
* @公众hao:程序员飞扬
* @description:
*/
public class SellTicket {
public static void main(String[] args) {
Sell sell = new Sell();
new Thread(sell).start();
new Thread(sell).start();
new Thread(sell).start();
}
}
class Sell implements Runnable{
Object object = new Object();
static int ticket = 10;
private boolean loop = true;
//同步方法(静态的)的锁为当前类本身
public synchronized static void m1(){//此时锁是加在Sell.class
}
public static void m2(){//在静态方法中实现同步代码快,类名.class
synchronized (Sell.class){
System.out.println("lalalala");
}
}
public /*synchronized*/ void m(){//同步方法
synchronized (/*this*/ object){//同步锁代码块,此时this指当前对象,锁object也可以,因为是操作的同一个对象
if(ticket <= 0){
setLoop(false);
System.out.println("没票了,售票结束");
return;
}
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("窗口" + Thread.currentThread().getName()+"卖出了一张票,剩余" + (--ticket) );
}
}
@Override
public void run() {
while(loop){
m();
}
}
public void setLoop(boolean loop) {
this.loop = loop;
}
}
三、线程死锁
/**
* @author:程序员飞扬
* @公众hao:程序员飞扬
* @description:
*/
public class DeadLock_ {
public static void main(String[] args) {
DeadLockDemo deadLockDemo1 = new DeadLockDemo(true);
DeadLockDemo deadLockDemo2 = new DeadLockDemo(false);
deadLockDemo1.start();
deadLockDemo2.start();
}
}
class DeadLockDemo extends Thread{
static Object o1 = new Object();
static Object o2 = new Object();
boolean flag;
public DeadLockDemo(boolean flag){
this.flag = flag;
}
public void run(){
if(flag){
synchronized (o1){
System.out.println(Thread.currentThread().getName() + "进入1");
synchronized (o2){
System.out.println(Thread.currentThread().getName() + "进入2");
}
}
}else{
synchronized (o2){
System.out.println(Thread.currentThread().getName() + "进入3");
synchronized (o1){
System.out.println(Thread.currentThread().getName() + "进入4");
}
}
}
}
}
运行结果:
四、释放锁
1.会释放锁
2.不会释放锁
五、线程练习题
1.线程调用练习
import java.util.Scanner;
/**
* @author:程序员飞扬
* @公众hao:程序员飞扬
* @description:
*/
public class HomeWork01 {
public static void main(String[] args) {
A a = new A();
B b = new B(a);
a.start();
b.start();
}
}
class A extends Thread{
private boolean loop = true;
public void setLoop(boolean loop) {
this.loop = loop;
}
int count;
@Override
public void run() {
while(loop){
++count;
System.out.print((int)((Math.random()*100 + 1))+ " ");//随机打印1~100之间的整数
if(count%10 == 0){
System.out.println();//每打印10个数换行
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class B extends Thread{
private A a;
private Scanner scanner = new Scanner(System.in);
public B(A a) {
this.a = a;
}
@Override
public void run() {
while(true){
System.out.println("输入指令'Q'表示退出:");
char c = scanner.next().toUpperCase().charAt(0);//接收控制台输入的字符'q'或'Q'
if(c == 'Q'){
a.setLoop(false);//将变量置为false,通知线程A退出
break;
}
}
}
}
输出:
输入指令'Q'表示退出:
80 79 77 25 58 63 97 47 39 99
2 34 44 73 79 87 98 q
Process finished with exit code 0
2.线程同步练习
/**
* @author:程序员飞扬
* @公众hao:程序员飞扬
* @description:
*/
public class HomeWork02 {
public static void main(String[] args) {
DrawMoney drawMoney = new DrawMoney();
Thread thread1 = new Thread(drawMoney);
thread1.setName("t1");
Thread thread2 = new Thread(drawMoney);
thread2.setName("t2");
thread1.start();
thread2.start();
}
}
class DrawMoney implements Runnable{
private int money = 5000;
@Override
public void run() {
System.out.println("当前一共有" + money);
while(true){
/**
* 1. 使用synchronized实现线程同步
* 2. 当多个线程执行到此处,就会去争夺this对象锁
* 3. 哪个线程获取到this对象锁,就执行synchronized代码块,执行完成后,会释放this对象锁
* 4.争夺不到this对象锁,就blocked,准备继续争夺
* 5. this对象锁是非公平锁
*/
synchronized (this){
if(money < 1000){
System.out.println("余额不足");
break;
}
money -= 1000;
System.out.println(Thread.currentThread().getName() + "取了1000元,当前余额" + money);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
输出:
当前一共有5000
当前一共有5000
t1取了1000元,当前余额4000
t2取了1000元,当前余额3000
t2取了1000元,当前余额2000
t1取了1000元,当前余额1000
t1取了1000元,当前余额0
余额不足
余额不足