线程复习
1. 线程的休眠
需求:编写一个抽取学员回答问题的程序,要求倒数三秒后输出被抽中的学员姓名
分析:
1. 创建String数组存放学员姓名
2. 利用随机数获取学员下标
3. 通过下标获取学员姓名
4. 倒计时3秒通过for循环使用Thread.sleep(1000)来实现,
Thread.sleep(1000);此方法为静态方法,写在哪个线程中,哪个线程就休眠
package com.wz.thread06;
import java.util.Random;
public class test01 {
/**
* 知识点:线程的休眠
* 需求:编写一个抽取学员回答问题的程序
* 要求倒数三秒后输出被抽中的学员姓名
*/
public static void main(String[] args) throws InterruptedException {
//创建String数组存放学员姓名
String[] names = {"张三","李四","王五","赵六","AAA","BBB","CCC"};
//利用随机数获取学员下标
Random random = new Random();
int index = random.nextInt(names.length);
//倒计时3秒通过for循环使用Thread.sleep(1000)来实现
for (int i = 3; i >=1 ; i--) {
System.out.println(i);
Thread.sleep(1000);
}
//通过下标获取学员姓名
System.out.println("抽到的学员是:"+names[index]);
}
}
2. 线程的礼让
需求:创建两个线程A,B,分别各打印1-100的数字,其中B一个线程,每打印一次,就礼让一次,观察实验结果
分析:
1. 创建A线程,继承Thread,重写run方法,打印1-100的数字
2. 创建B线程,继承Thread,重写run方法,打印1-100的数字,每打印一次,就礼让一次
Thread.yield();
此方法为静态方法,此方法写在哪个线程中,哪个线程就礼让
所谓的礼让是指当前线程退出CPU资源,并转到就绪状态,接着再抢
package com.wz.thread07;
public class A extends Thread{
@Override
public void run() {
for (int i = 1; i <=100 ; i++) {
System.out.println("A线程"+i);
}
}
}
package com.wz.thread07;
public class B extends Thread{
@Override
public void run() {
for (int i = 1; i <=100 ; i++) {
System.out.println("B线程"+i);
Thread.yield();
}
}
}
package com.wz.thread07;
public class test01 {
/**
* 需求:创建两个线程A,B
* 分别各打印1-100的数字
* 其中B一个线程,每打印一次,就礼让一次,观察实验结果
*/
public static void main(String[] args) {
A a = new A();
B b = new B();
a.start();
b.start();
}
}
3. 线程的合并
需求:主线程和子线程各打印200次,从1开始每次增加1,当主线程打印到10之后,让子线程先打印完再打印主线程
分析:
1. 创建主线程,打印1~200
2. 创建子线程,打印1~200
3. 判断当主线程打印到10,用join()方法将子线程加入主线程
t.join(); 合并方法
package com.wz.thread08;
public class MyThread extends Thread{
@Override
public void run() {
for (int i = 1; i <=200 ; i++) {
System.out.println("子线程"+i);
}
}
}
package com.wz.thread08;
public class test01 {
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
myThread.start();
for (int i = 1; i <=200 ; i++) {
System.out.println("主线程"+i);
if (i>10){
myThread.join();
}
}
}
}
4. 线程的中断
- stop();立即终止,该方法已经过时。无法保证功能的完整性
- run()执行完毕,利用boolean值来控制线程的中断
- interrupt();中断这个线程(改变线程状态)
package com.wz.thread09;
public class MyThread extends Thread{
@Override
public void run() {
//判断当前线程是否消亡(True-消亡 false- 未消亡)
while (!Thread.currentThread().isInterrupted()){
System.out.println("AAAA");
System.out.println("BBBB");
System.out.println("CCCC");
System.out.println("DDDD");
System.out.println("EEEE");
System.out.println(Thread.currentThread().isInterrupted());
}
}
}
package com.wz.thread09;
public class test01 {
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
myThread.start();
myThread.sleep(5000);
//改变线程状态,开始为false(未消亡)--> 调用后 True(消亡)
myThread.interrupt();
}
}
5. 后台线程(守护线程)
守护线程 默默守护着前台线程,当所有的前台线程都消亡后,守护线程会自动消亡
注意:垃圾回收器就是守护线程
t.setDaemon(true);
package com.wz.thread10;
public class A extends Thread{
@Override
public void run() {
while (true){
System.out.println("后台线程守护着前台线程!");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package com.wz.thread10;
public class test01 {
public static void main(String[] args) throws InterruptedException {
A a = new A();
a.setDaemon(true);
a.start();
for (int i = 1; i <=20 ; i++) {
System.out.println("前台线程"+i);
Thread.sleep(1000);
}
}
}
/**
* 重写
* 概念:父类方法在子类中重新写一遍
* 应用场景:父类方法不满足子类需求,考虑在子类中重写父类的方法
* 条件:
* 1.在子类中重写
* 2.返回值、方法名、参数列表、抛出异常类型必须和重写父类的方法的一致
* 3.访问修饰符不能比父类更加严格
*/
6. 线程的生命周期
生产者消费者模型
创建产品类(Phone)
package producer_consumer_01;
//产品类
public class Phone {
private String brand;//品牌
private double price;//价格
private boolean store;//仓库-false空
public Phone() {
}
public Phone(String brand, double price) {
this.brand = brand;
this.price = price;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public boolean isStore() {
return store;
}
public void setStore(boolean store) {
this.store = store;
}
@Override
public String toString() {
return "Phone [brand=" + brand + ", price=" + price + "]";
}
}
创建生产者线程Producer extends Thread,重写run()方法
package producer_consumer_01;
//生产者线程
public class Producer extends Thread{
private Phone phone;
public Producer(Phone phone) {
this.phone = phone;
}
@Override
public void run() {
boolean flag = true;
while(true){
//加锁
synchronized (phone) {
if(phone.isStore()){
try {
phone.wait();//等待:1.将等待的线程记录在对象监视器中 2.释放锁资源 3.让当前线程进入到阻塞状态
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(flag){
phone.setBrand("华为");
phone.setPrice(3999);
}else{
phone.setBrand("小米");
phone.setPrice(1999);
}
flag = !flag;
phone.setStore(true);
phone.notify();//唤醒:唤醒的对象监视器中随机的一个线程
}
}
}
}
创建消费者线程 Consumer extends Thread,重写run()方法
package producer_consumer_01;
//消费者线程
public class Consumer extends Thread{
private Phone phone;
public Consumer(Phone phone) {
this.phone = phone;
}
@Override
public void run() {
while(true){
synchronized(phone){
if(!phone.isStore()){
try {
phone.wait();//等待:1.将等待的线程记录在对象监视器中 2.释放锁资源 3.让当前线程进入到阻塞状态
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(phone.getBrand() + " -- " + phone.getPrice());
phone.setStore(false);
phone.notify();//唤醒:唤醒:唤醒的对象监视器中随机的一个线程
}
}
}
}
测试类
package producer_consumer_01;
public class test01 {
/**
* 知识点:生产者消费者模型
* 分析:
* 产品类
* 生产者线程不断的生产产品(set())
* 消费者线程不断的消费产品(get())
*
* 情况:一个生产者一个消费者的情况
* 最终目的:生产一个、消费一个
*
* 步骤:
* 1.让生产者消费者线程操作同一个资源(产品对象)
* bug:
*/
public static void main(String[] args) {
Phone phone = new Phone();
Producer p = new Producer(phone);
Consumer c = new Consumer(phone);
p.start();
c.start();
}
}
标签:String,Thread,void,phone,线程,2023,public,礼让
From: https://blog.51cto.com/u_15098423/6636194