目录
一、线程状态
1.线程五大状态
- 新建状态
- 就绪状态
- 运行状态
- 阻塞状态
- 死亡状态
运行过程描述
2.线程方法
2.1停止线程
案例:
public class ThreadStop implements Runnable {
private Boolean flag = true;
@Override
public void run() {
int count = 0;
while (flag) {
System.out.println("线程正在运行" + count++);
}
}
public void stop() {
this.flag = false;
}
public static void main(String[] args) {
ThreadStop stop = new ThreadStop();
new Thread(stop).start();
for (int i = 0; i < 1000; i++) {
System.out.println("主函数正在运行" + i);
if (i == 900) {
stop.stop();
}
}
}
}
2.2线程休眠
案例:
public class ThreadSleep {
public static void sleepThread() {
int num = 10;
while (true) {
try {
System.out.println("倒计时:" + num--);
Thread.sleep(1000);
if (num <= 0) {
break;
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) {
sleepThread();
}
}
2.3线程礼让
线程礼让只是重新抢夺CPU的调度,礼让不一定会成功、只是再给其它线程一个机会而已。
案例:
public class ThreadYield implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "开始运行");
Thread.yield();
System.out.println(Thread.currentThread().getName() + "结束运行");
}
public static void main(String[] args) {
new Thread(new ThreadYield(), "线程1").start();
new Thread(new ThreadYield(), "线程2").start();
}
}
2.4线程插队
简单的理解为线程插队就可以了
案例:
public class ThreadJoin implements Runnable {
@Override
public void run() {
for (int i = 1; i <= 1000; i++) {
System.out.println("我是VIP我要插队" + i);
}
}
public static void main(String[] args) throws InterruptedException {
ThreadJoin threadJoin = new ThreadJoin();
Thread thread = new Thread(threadJoin);
thread.start();
for (int i = 1; i <= 100; i++) {
System.out.println("我是普通用户:" + i);
if (i == 50) {
thread.join();
}
}
}
}
3.线程状态观测
案例:
public class GetThreadState implements Runnable {
// 实现Runnable接口,重写run方法
@Override
public void run() {
// 循环一次
for (int i = 0; i < 1; i++) {
try {
// 休眠500毫秒
Thread.sleep(500);
} catch (InterruptedException e) {
// 抛出运行时异常
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) {
// 创建GetThreadState对象
Thread thread = new Thread(new GetThreadState());
// 输出线程状态
System.out.println(thread.getState());
thread.start();
System.out.println(thread.getState());
while (thread.getState()!= Thread.State.TERMINATED){
System.out.println(thread.getState());
}
System.out.println(thread.getState());
}
}
4.线程优先级
线程优先级的高低只是被CPU调用的概率大
案例:
public class ThreadPriority implements Runnable {
@Override
public void run() {
synchronized (ThreadPriority.class){
System.out.println(Thread.currentThread().getName() + "--->" + Thread.currentThread().getPriority());
}
}
public static void main(String[] args) {
Thread one = new Thread(new ThreadPriority(), "one");
one.setPriority(1);
one.start();
Thread two = new Thread(new ThreadPriority(), "two");
two.setPriority(2);
two.start();
Thread three = new Thread(new ThreadPriority(), "three");
three.setPriority(3);
three.start();
Thread four = new Thread(new ThreadPriority(), "four");
four.setPriority(4);
four.start();
Thread five = new Thread(new ThreadPriority(), "five");
five.setPriority(5);
five.start();
Thread defaultPriority = new Thread(new ThreadPriority(), "defaultPriority");
defaultPriority.start();
Thread maxPriority = new Thread(new ThreadPriority(), "maxPriority");
maxPriority.setPriority(Thread.MAX_PRIORITY);
maxPriority.start();
}
}
5.守护(daemon)线程
皇上和宫女,皇上活着宫女一直在,皇上死了宫女陪葬
案例:
package com.example.threadstudy.state;
public class DaemonThread {
public static void main(String[] args) {
// 创建一个God对象
God god = new God();
// 创建一个Person对象
Person person = new Person();
// 创建一个Thread对象,并将God对象作为参数传入
Thread thread = new Thread(god);
// 将Thread对象设置为守护线程
thread.setDaemon(true);
// 启动Thread对象
thread.start();
// 创建一个新的Thread对象,并将Person对象作为参数传入
new Thread(person, "one").start();
new Thread(person, "two").start();
}
}
class God implements Runnable {
// 实现Runnable接口,重写run方法
@Override
public void run() {
// 无限循环
while (true)
// 输出上帝一直保佑你
System.out.println("上帝一直保佑你");
}
}
class Person implements Runnable {
// 实现Runnable接口,重写run方法
@Override
public void run() {
// 循环100次
for (int i = 0; i < 100; i++) {
// 输出"我还在坚持"
System.out.println(Thread.currentThread().getName() + "我还在坚持");
}
// 输出"坚持不住了,上帝再见"
System.out.println(Thread.currentThread().getName() + "坚持不住了,上帝再见");
}
}
二、线程同步
1.介绍
多个线程操作同一个资源
2.不安全的线程案例
package com.example.threadstudy.unsafethread;
public class BuyTicket implements Runnable {
private int ticket = 10;
@Override
public void run() {
while (true) {
if (hasTicket()) {
try {
Thread.sleep(50);
System.out.println(Thread.currentThread().getName() + "买到了第" + ticket-- + "张票");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} else {
break;
}
}
System.out.println("票已经卖完了");
}
public Boolean hasTicket() {
return ticket > 0;
}
public static void main(String[] args) {
new Thread(new BuyTicket(), "窗口1").start();
new Thread(new BuyTicket(), "窗口2").start();
new Thread(new BuyTicket(), "窗口3").start();
}
}
3.同步方法
同步方法,锁的是当前对象,未添加synchronized的方法也会被锁上,浪费资源
实现:
public class BuyTicket {
public static void main(String[] args) {
BuyTicketThread buyTicketThread = new BuyTicketThread();
Thread thread1 = new Thread(buyTicketThread, "窗口1");
Thread thread2 = new Thread(buyTicketThread, "窗口2");
Thread thread3 = new Thread(buyTicketThread, "窗口3");
thread1.start();
thread2.start();
thread3.start();
}
}
class BuyTicketThread implements Runnable {
private int ticket = 10;
private boolean hasTicketFlag = true;
@Override
public void run() {
while (hasTicketFlag) {
buyTicket();
}
System.out.println("票卖完了");
}
public synchronized void buyTicket() {
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "买到了第" + ticket + "张票");
ticket--;
} else {
hasTicketFlag = false;
}
}
}
4.同步块
锁的是需要修改的变量,需要增删改查的对象
实现:
package com.example.threadstudy.safethread;
public class SafeBank {
public static void main(String[] args) {
Account1 account = new Account1(100, "结婚基金");
Drawing1 you = new Drawing1(account, 50, "展堂");
Drawing1 girlfriend = new Drawing1(account, 100, "sad");
you.start();
girlfriend.start();
}
}
//账户
class Account1 {
int money;//余额
String cardName;//卡名
public Account1(int money, String cardName) {
this.money = money;
this.cardName = cardName;
}
}
//银行:模拟取款
class Drawing1 extends Thread {
Account1 account;//账户
int drawingMoney;//取金额
int nowMoney;//你手里的钱
public Drawing1(Account1 account, int drawingMoney, String name) {
super(name);
this.account = account;
this.drawingMoney = drawingMoney;
}
//取钱
@Override
public void run() {
//锁的对象就是变量的量,需要增删改查的对象
synchronized (account) {
//判断是否有钱
if (account.money - drawingMoney < 0) {
System.out.println(Thread.currentThread().getName() + "余额不足,不能进行取钱");
return;
}
try {
Thread.sleep(1000);//放大问题的发生性
} catch (InterruptedException e) {
e.printStackTrace();
}
//卡内金额 = 余额-你的钱
account.money = account.money - drawingMoney;
//你手里的钱
nowMoney = nowMoney + drawingMoney;
System.out.println(account.cardName + "余额为:" + account.money);
//this.getName()==Thread.currentThread().getName()
System.out.println(this.getName() + "手里的钱:" + nowMoney);
}
}
}
5.死锁
实现:
/**
* 死锁:多个线程互相抱着对方需要的资源,然后形成僵持
* 解决:一个锁只锁一个对象
*/
class DeadLock {
public static void main(String[] args) {
Makeup makeup = new Makeup(0, "灰姑娘");
Makeup makeup1 = new Makeup(1, "白雪公主");
makeup.start();
makeup1.start();
}
}
//口红
class Lipstick { }
//镜子
class Mirror { }
class Makeup extends Thread {
//需要的资源只有一份,用static保证只有一份
static Lipstick lipstick = new Lipstick();
static Mirror mirror = new Mirror();
int choice;//选择
String girlName;//使用化妆品的人
public Makeup(int choice, String girlName) {
this.choice = choice;
this.girlName = girlName;
}
@Override
public void run() {
//化妆
try {
makeup();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void makeup() throws InterruptedException {
if (choice == 0) {
synchronized (lipstick) {//获得口红的锁
System.out.println(this.girlName + "获得口红的锁");
Thread.sleep(1000);
synchronized (mirror) {//一秒钟后想获得镜子
System.out.println(this.girlName + "获得镜子的锁");
}
}
} else {
synchronized (mirror) {//获得口红镜子
System.out.println(this.girlName + "获得镜子的锁");
Thread.sleep(2000);
synchronized (lipstick) {//二秒钟后想获得的锁
System.out.println(this.girlName + "获得口红的锁");
}
}
}
}
}
解决方式:不要相互占有资源
/**
* 死锁:多个线程互相抱着对方需要的资源,然后形成僵持
* 解决:一个锁只锁一个对象
*/
class DeadLock {
public static void main(String[] args) {
Makeup makeup = new Makeup(0, "灰姑娘");
Makeup makeup1 = new Makeup(1, "白雪公主");
makeup.start();
makeup1.start();
}
}
//口红
class Lipstick { }
//镜子
class Mirror { }
class Makeup extends Thread {
//需要的资源只有一份,用static保证只有一份
static Lipstick lipstick = new Lipstick();
static Mirror mirror = new Mirror();
int choice;//选择
String girlName;//使用化妆品的人
public Makeup(int choice, String girlName) {
this.choice = choice;
this.girlName = girlName;
}
@Override
public void run() {
//化妆
try {
makeup();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void makeup() throws InterruptedException {
if (choice == 0) {
synchronized (lipstick) {//获得口红的锁
System.out.println(this.girlName + "获得口红的锁");
Thread.sleep(1000);
}
synchronized (mirror) {//一秒钟后想获得镜子
System.out.println(this.girlName + "获得镜子的锁");
}
} else {
synchronized (mirror) {//获得口红镜子
System.out.println(this.girlName + "获得镜子的锁");
Thread.sleep(2000);
}
synchronized (lipstick) {//二秒钟后想获得的锁
System.out.println(this.girlName + "获得口红的锁");
}
}
}
}
死锁避免办法
6.Lock(锁)
//测试Lock锁
public class Demo32_ThreadLock {
public static void main(String[] args) {
TestLock testLock = new TestLock();
new Thread(testLock).start();
new Thread(testLock).start();
new Thread(testLock).start();
}
}
class TestLock implements Runnable {
int tickerNums = 10;
//定义Lock锁
private final ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
//加锁
try {
lock.lock();
if (tickerNums <= 0) {
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(tickerNums--);
} catch (Exception e) {
e.printStackTrace();
} finally {
//解锁
lock.unlock();
}
}
}
}
7.synchroized与Lock对比
五、线程通信问题
生产者消费者模式的问题
1.线程通信方法
2.线程通信问题解决方式
/**
* 测试:生产者消费者模型-->利用缓冲区解决:管程法
*/
public class ThreadPC {
public static void main(String[] args) {
SynContainer synContainer = new SynContainer();
new Producer(synContainer).start();
new Consumer(synContainer).start();
}
}
//生产者
class Producer extends Thread {
//容缓冲区
SynContainer container;
public Producer(SynContainer container) {
this.container = container;
}
//生产
@Override
public void run() {
for (int i = 0; i < 100; i++) {
container.push(new Product(i));
System.out.println("生产了" + i + "件产品");
}
}
}
//消费者
class Consumer extends Thread {
//容缓冲区
SynContainer container;
public Consumer(SynContainer container) {
this.container = container;
}
//消费
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("消费了-->" + container.pop().id + "件产品");
}
}
}
//产品
class Product {
int id;//产品编号
public Product(int id) {
this.id = id;
}
}
//缓冲区
class SynContainer {
//需要一个容器大小
Product[] products = new Product[10];
//容器计数器
int count = 0;
//生产者放入产品
public synchronized void push(Product product) {
//如果容器满了,需要等待消费者消费
/*如果是if的话,假如消费者1消费了最后一个,这是index变成0此时释放锁被消费者2拿到而不是生产者拿到,这时消费者的wait是在if里所以它就直接去消费index-1下标越界,如果是while就会再去判断一下index得值是不是变成0了*/
while (count == products.length) {
//通知消费者消费,等待生产
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果没有满,需要丢入产品
products[count] = product;
count++;
//通知消费者消费
this.notifyAll();
}
//消费者消费产品
public synchronized Product pop() {
//判断是否能消费
while (count <= 0) {
//等待生产者生产
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果可以消费
count--;
Product product = products[count];
//吃完了 通知生产者生产
this.notifyAll();
return product;
}
}
/**
* 测试:生产者消费者模型-->利用缓冲区解决:管程法
*/
public class ThreadPC {
public static void main(String[] args) {
SynContainer synContainer = new SynContainer();
new Producer(synContainer).start();
new Consumer(synContainer).start();
}
}
//生产者
class Producer extends Thread {
//容缓冲区
SynContainer container;
public Producer(SynContainer container) {
this.container = container;
}
//生产
@Override
public void run() {
for (int i = 0; i < 100; i++) {
container.push(new Product(i));
System.out.println("生产了" + i + "件产品");
}
}
}
//消费者
class Consumer extends Thread {
//容缓冲区
SynContainer container;
public Consumer(SynContainer container) {
this.container = container;
}
//消费
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("消费了-->" + container.pop().id + "件产品");
}
}
}
//产品
class Product {
int id;//产品编号
public Product(int id) {
this.id = id;
}
}
//缓冲区
class SynContainer {
//需要一个容器大小
Product[] products = new Product[10];
//容器计数器
int count = 0;
//生产者放入产品
public synchronized void push(Product product) {
//如果容器满了,需要等待消费者消费
/*如果是if的话,假如消费者1消费了最后一个,这是index变成0此时释放锁被消费者2拿到而不是生产者拿到,这时消费者的wait是在if里所以它就直接去消费index-1下标越界,如果是while就会再去判断一下index得值是不是变成0了*/
while (count == products.length) {
//通知消费者消费,等待生产
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果没有满,需要丢入产品
products[count] = product;
count++;
//通知消费者消费
this.notifyAll();
}
//消费者消费产品
public synchronized Product pop() {
//判断是否能消费
while (count <= 0) {
//等待生产者生产
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果可以消费
count--;
Product product = products[count];
//吃完了 通知生产者生产
this.notifyAll();
return product;
}
}
六、线程池
public class ThreadPool {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(10);
//执行
executorService.execute(new testThreadPool());
executorService.execute(new testThreadPool());
executorService.execute(new testThreadPool());
executorService.execute(new testThreadPool());
executorService.execute(new testThreadPool());
executorService.execute(new testThreadPool());
//关闭连接
executorService.shutdown();
}
}
class testThreadPool implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}