Day17_进程(上)
创建线程
第一种方式:继承Thread类
//普通类想要具备多线程的能力,继承Thread类
//线程类
public class Demo01 extends Thread {
@Override
//线程体--以后要争抢资源做的事
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println("Demo01---"+i);
}
}
}
public class test {
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {
System.out.println("main01---"+i);
}
Demo01 tt=new Demo01();
tt.start();//线程的启动
for (int i = 1; i <= 5; i++) {
System.out.println("main02---"+i);
}
}
}
输出结果:
main01---1
main01---2
main01---3
main01---4
main01---5
main02---1
main02---2
main02---3
Demo01---1
main02---4
main02---5
Demo01---2
Demo01---3
Demo01---4
Demo01---5
设置读取线程名称
第一种方式:使用setName()设置线程名称
public class test01 {
public static void main(String[] args) {
Thread.currentThread().setName("The main---");
Demo01 tt=new Demo01();
tt.setName("Demo01");
tt.start();//线程的启动
for (int i = 1; i <= 5; i++) {
System.out.println(Thread.currentThread().getName()+i);
}
}
}
输出:
Demo011
The main---1
Demo012
The main---2
Demo013
Demo014
Demo015
The main---3
The main---4
The main---5
第二种方式:使用构造器设置线程名称
public class Demo02 extends Thread {
public Demo02(String name) {
super(name);
}
@Override
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println(this.getName()+i);
}
}
}
public class test02 {
public static void main(String[] args) {
Thread.currentThread().setName("The main---");
//通过构造器设置线程名称
Demo02 tt=new Demo02("Demo02");
tt.start();//线程的启动
for (int i = 1; i <= 5; i++) {
System.out.println(Thread.currentThread().getName()+i);
}
}
}
输出:
Demo021
The main---1
Demo022
The main---2
Demo023
Demo024
Demo025
The main---3
The main---4
The main---5
龟兔赛跑
兔子:Tuzi类
public class Tuzi extends Thread{
public Tuzi(String name) {
super(name);
}
@Override
public void run() {
while(true){
System.out.println(Thread.currentThread().getName()+"===我是兔子我在跑!");
}
}
}
乌龟:Wugui类
public class Wugui extends Thread{
public Wugui(String name) {
super(name);
}
@Override
public void run() {
while(true){
System.out.println(Thread.currentThread().getName()+"===我是乌龟我在跑!");
}
}
}
测试:guituTest类
public class guituTest {
public static void main(String[] args) {
Tuzi tz=new Tuzi("兔子");
tz.start();
Wugui wg=new Wugui("乌龟");
wg.start();
}
}
运行结果:一直在无序输出“兔子=我是兔子我在跑!
乌龟=我是乌龟我在跑!”这两句话。
抢火车票
HuoChePiao类
public class HuoChePiao extends Thread{
private static int ticketNum=10;
public HuoChePiao(String name){
super(name);
}
@Override
//每个窗口就是一个线程
public void run() {
//每个窗口下有100人买票
for (int i = 0; i <= 100; i++) {
if (ticketNum > 0) {
System.out.println("我在" + this.getName() + "买到了火车票,剩余的第" + ticketNum-- + "张车票");
}
}
}
}
ChePiaoTest类
public class ChePiaoTest {
public static void main(String[] args) {
HuoChePiao hcp1=new HuoChePiao("窗口1");
hcp1.start();
HuoChePiao hcp2=new HuoChePiao("窗口2");
hcp2.start();
HuoChePiao hcp3=new HuoChePiao("窗口3");
hcp3.start();
HuoChePiao hcp4=new HuoChePiao("窗口4");
hcp4.start();
}
}
输出:
我在窗口1买到了火车票,剩余的第10张车票
我在窗口4买到了火车票,剩余的第7张车票
我在窗口4买到了火车票,剩余的第5张车票
我在窗口3买到了火车票,剩余的第8张车票
我在窗口2买到了火车票,剩余的第9张车票
我在窗口3买到了火车票,剩余的第3张车票
我在窗口4买到了火车票,剩余的第4张车票
我在窗口1买到了火车票,剩余的第6张车票
我在窗口3买到了火车票,剩余的第1张车票
我在窗口2买到了火车票,剩余的第2张车票
第二种方式:实现Runnable接口
public class Demo03 implements Runnable{
@Override
public void run() {
for (int i = 1; i <=10; i++) {
System.out.println(Thread.currentThread().getName()+"---"+i);
}
}
}
public class test03 {
public static void main(String[] args) {
//创建线程对象
Demo03 tt=new Demo03();
//启动线程
//两个类之间若要产生关联,利用有参构造器。
Thread t=new Thread(tt);
t.start();
for (int i = 1; i <=10 ; i++) {
System.out.println(Thread.currentThread().getName()+"---"+i);
}
}
}
输出:
Thread-0---1
main---1
Thread-0---2
main---2
main---3
main---4
main---5
Thread-0---3
main---6
Thread-0---4
main---7
Thread-0---5
Thread-0---6
main---8
Thread-0---7
main---9
Thread-0---8
main---10
Thread-0---9
Thread-0---10
静态代理模式
创建接口BeiRenZhui
public interface BeiRenZhui {
void maiHua();
void kouHong();
}
新建类(被追的人JinHaiXin)
public class JinHaiXin implements BeiRenZhui{
@Override
public void maiHua() {
System.out.println("买蓝色妖姬。。。花。。。");
}
@Override
public void kouHong() {
System.out.println("女王的权杖。。。口红。。。");
}
}
新建类(被追的人XiaoPang)
public class XiaoPang implements BeiRenZhui{
@Override
public void maiHua() {
System.out.println("买小雏菊。。。");
}
@Override
public void kouHong() {
System.out.println("买小羊皮。。。");
}
}
新建代理人Shan
public class Shan implements BeiRenZhui{
BeiRenZhui brz;
public Shan(BeiRenZhui brz){
this.brz=brz;
}
@Override
public void maiHua() {
brz.maiHua();
}
@Override
public void kouHong() {
brz.kouHong();
}
}
新建追求者
public class ChiXinRen {
public static void main(String[] args) {
//先委托Shan追求JinHaiXin
JinHaiXin jhx=new JinHaiXin();
Shan s=new Shan(jhx);
s.maiHua();
s.kouHong();
System.out.println("-------------");
//未果,又委托Shan追求XiaoPang
XiaoPang xp=new XiaoPang();
Shan ss=new Shan(xp);
ss.maiHua();
ss.kouHong();
}
}
运行结果:
买蓝色妖姬。。。花。。。
女王的权杖。。。口红。。。
-------------
买小雏菊。。。
买小羊皮。。。
第二种方式抢火车票
用此种方式比较好,原因:
1.共享资源。
2.实现接口,所以可以继承其他的类,但是第一种方式,java单继承,不能继承其他的类。
Ticket类
public class Ticket implements Runnable{
private int ticketNum=10;
@Override
public void run() {
for (int i = 1; i <=ticketNum ; i++) {
if(ticketNum>0){
System.out.println("我在"+Thread.currentThread().getName()+"买到了剩余的第"+ticketNum--+"张火车票!");
}
}
}
}
public class ticketTest {
public static void main(String[] args) {
Ticket tk=new Ticket();
Thread t1=new Thread(tk,"窗口1");
t1.start();
Thread t2=new Thread(tk,"窗口2");
t2.start();
Thread t3=new Thread(tk,"窗口3");
t3.start();
}
}
运行结果
我在窗口2买到了剩余的第10张火车票!
我在窗口1买到了剩余的第8张火车票!
我在窗口3买到了剩余的第9张火车票!
我在窗口3买到了剩余的第5张火车票!
我在窗口1买到了剩余的第6张火车票!
我在窗口2买到了剩余的第7张火车票!
我在窗口1买到了剩余的第3张火车票!
我在窗口3买到了剩余的第4张火车票!
第三种方式
之前的第一种、第二种方式:
public class Ticket implements Runnable{
public void run(){
}
}
run()方法不可以有返回值,并且不可以出现异常。
第三种方式是JDK1.5之后加入的。
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
//第三种方式:实现Callable接口,在实现的同时,加入泛型。这个泛型是call方法的返回值类型。
public class Demo04 implements Callable<Integer> {
//重写call方法,这个方法:有返回值,有抛出异常
@Override
public Integer call() throws Exception {
return new Random().nextInt(10);
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
//缺点:创建线程方式比较繁琐
//创建线程对象
Demo04 t=new Demo04();
//启动线程
FutureTask<Integer> ft=new FutureTask<>(t);
Thread tt=new Thread(ft);
tt.start();
//返回值自己获取
System.out.println(ft.isDone());
Integer i=ft.get();
System.out.println(i);
//获取返回值之后线程才结束
System.out.println(ft.isDone());
}
}
线程的生命周期
新生阶段
Thread tt=new Thread();
运行start()方法后进入就绪阶段
就绪阶段
有资格,无资源。万事俱备,只欠CPU调度。
CPU调度:run(),call()
运行阶段
有资格,有资源
运行阶段之后有两种可能:阻塞阶段或者消亡阶段。
遇到IO流等阻塞方法,进入阻塞阶段。
阻塞阶段
无资格,让资源。
解除阻塞后进入就绪阶段。
消亡阶段
-
正常执行,正常结束
-
出现异常
-
调用stop()方法
影响生命周期的方法
优先级别
public class guituTest {
public static void main(String[] args) {
Tuzi tz=new Tuzi("兔子");
tz.setPriority(2);
tz.start();
Wugui wg=new Wugui("乌龟");
wg.setPriority(8);
wg.start();
}
}
运行结果
兔子===我是兔子我在跑!
兔子===我是兔子我在跑!
兔子===我是兔子我在跑!
兔子===我是兔子我在跑!
兔子===我是兔子我在跑!
兔子===我是兔子我在跑!
兔子===我是兔子我在跑!
兔子===我是兔子我在跑!
乌龟===我是乌龟我在跑!
兔子===我是兔子我在跑!
兔子===我是兔子我在跑!
乌龟===我是乌龟我在跑!
乌龟===我是乌龟我在跑!
乌龟===我是乌龟我在跑!
乌龟===我是乌龟我在跑!
乌龟===我是乌龟我在跑!
乌龟===我是乌龟我在跑!
乌龟===我是乌龟我在跑!
乌龟===我是乌龟我在跑!
乌龟===我是乌龟我在跑!
说明:优先级别高,只能说明 优先 被CPU调用的概率高,而不是一定优先被调度。