折纸的不归路(20)

一.线程

进程:程序在计算机上进行资源调度和分配的最小单元
线程:一个进程启动至少一条线程,该线程叫做主线程,线程是程序内部进行资源调度的最小单元
多线程:

一.线程三要素

CPU:那个程序抢到了CPU的执行权,哪个程序就开始执行
代码:线程执行体,主线程之外的线程需要做什么事情
数据:
宏观:程序中交互的所有变量
微观:变量中保存的数据
为什么学习多线程
1.解决一些耗时操作
2.解决一些业务逻辑的并发操作

二.Java中的多线程:

多线程是编码层面的多线程,比较简单
java.lang.Thread
java中开启一个线程就是创建了一个Thread对象
java程序中main方法就是主线程

创建多线程的两种方式

1.继承Thread类

实例变量是互不影响的
静态变量是可能会产生影响的

相关代码实现

package day18;
/**
 * 继承Thread
 * @author Acer
 *
 */
public class FirstThread extends Thread{
	private int i;
	//重写run方法
	@Override
	public void run() {
		//线程执行体
		//一旦线程开始执行,则运行run方法里的内容
		for(;i<100;i++) {
			//输出一下i以及该线程的名字
			System.out.println(this.getName()+" "+i);
			try {
				sleep(00);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}//线程睡眠1秒中,相当于两条结果的中间间隔1秒
		}
	}
	
	public static void main(String[] args) {
		//让main线程也执行一下循环
		for(int i=0;i<100;i++) {
			Thread mt = Thread.currentThread();
			System.out.println(mt.getName()+" "+i);
			//当i等于20的时候,创建新的线程
			if(i==20) {
				Thread t1 = new FirstThread();//Thread-0
				Thread t2 = new FirstThread();//Thread-1
//			启动线程,调用start方法
			t1.start();
			t2.start();
			}
			
		}
	}
}

2.实现Runnable接口

因为Runnable接口的实现类没有start方法,所以还需要依赖Thread进行线程创建
总之一句话,java中只有Thread的实例代表一条线程
实例变量:
如果传入的是用一个Runnable的实现类实例,则会互相影响
如果传入的是两个不同的Runnable的实现类实例,则不会产生影响
静态变量:

package day18;

/**
 * 实现Runnable接口
 * 
 * @author Acer
 *
 */
public class SecondThread implements Runnable {
	private int i;


	@Override
	public void run() {
		for (; i < 100; i++) {
			System.out.println(Thread.currentThread().getName() + "id为" +Thread.currentThread().getId()+"优先级为"+Thread.currentThread().getPriority()+"数值为"+i);
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

	public static void main(String[] args) {
		for (int i = 0; i < 100; i++) {
			Thread mt = Thread.currentThread();
			System.out.println(mt.getName() + "id为" + mt.getId() + "优先级为" + mt.getPriority() + "数值为" + i);
			if (i == 10) {
				SecondThread st1 = new SecondThread();
				SecondThread st2 = new SecondThread();
				// 因为st1和st2中没有start方法
				// 所以实现了Runna接口的线程还需要依赖于Thread
				Thread t1 = new Thread(st1,"线程一");
				Thread t2 = new Thread(st2,"线程二");
				t1.start();
				t2.start();
			}
		}
	}
}

线程的生命周期

1.新建状态(New)
创建Thread实例
Thread t = new Thread();
2.就绪状态(Runnable)
执行t.start
代表线程准备好开始CPU的抢夺
3.运行状态(Running)
执行run()方法里的代码块
4.阻塞状态(Blocked)
a.sleep
睡眠时间到了
被其他线程打断
有其他线程加入
则会退出阻塞状态转为就绪状态
b.join
当前线程阻塞,由调用join的线程先执行,
执行完毕之后当前线程进入就绪状态
5.死亡状态(Dead)
整个线程执行完毕,不能再开启该线程
会报异常,非法的线程状态
死亡状态的代码实现

package day18;

public class DeadThread extends Thread {
	int i = 0;

	@Override
	public void run() {
		for (; i < 100; i++)
			//输出线程是否活着
			System.out.println(getName() + " " + i+" "+isAlive());
	}
	public static void main(String[] args) {
		DeadThread dt = new DeadThread();
		System.out.println(dt.getState());
		for(int i=0;i<100;i++) {
			Thread mt = Thread.currentThread();
			System.out.println(mt.getName() + " " + i+" "+mt.isAlive());
			if(i==10) {
				dt.start();
			}
			//当线程dt死亡后再开启一次
//			if(i>10 || dt.isAlive() == false) {
//				dt.start();
//			}
			if(i==60) {
				dt.start();
				System.out.println(dt.getState().toString());
			}
			System.out.println(dt.getState());
		}
		
	}
}

运行时会在i=60时报错,已经死亡的线程无法再次开启

初级龟兔赛跑:
乌龟和兔子的速度用随机数0-10

package day18;

/**
 * 龟兔赛跑
 * 
 * @author Acer
 *
 */
public class RaceTest extends Thread {
	private int sum = 0;
	//可以给一个验证的旗标,
	private static boolean isEnd = false;
	public RaceTest(String name) {
		super(name);
	}

	@Override
	public void run() {
		while(sum<100) {
			if(isEnd == true) return;//stop();
			//准备一个速度
			int speed = (int)(Math.random()*11);
			sum+=speed;
			//先来给跑的线程准备一个睡眠
			//
			System.out.println(getName()+"跑了"+sum+"米");
			//先来给跑的线程准备一个睡眠
			try {
				sleep(200);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		isEnd = true;
		System.out.println(getName()+"赢了!");
	}
	public static void main(String[] args) throws InterruptedException {
		System.out.println("比赛开始");
		//准备乌龟和兔子的线程
		
		//作弊:兔子抢夺线程的机会大一点
		RaceTest rabbit = new RaceTest("兔子");
		RaceTest tortoise = new RaceTest("乌龟");
		//在线程转入就绪状态前,设置优先级
		rabbit.setPriority(Thread.MAX_PRIORITY);//作弊过程
		tortoise.setPriority(Thread.MIN_PRIORITY);//作弊过程
		//起跑
		rabbit.start();
		tortoise.start();
		//join()代表该线程加入,线程等待调用join的线程结束之后进入就绪状态
		rabbit.join();
		tortoise.join();
		System.out.println("比赛结束");
	}
}

在代码中给兔子和乌龟分别设置max和min的优先级,可以使兔子比乌龟先到达100.但是可能是玄学吧,在测试的时候乌龟尽管是min的优先级,却还是常胜将军

线程安全

对于多个线程操纵的统一数据进行加锁,可以让某一线程在操作数据的时候,
别的线程如果也要访问该数据,将无法访问该数据,导致线程阻塞

二.心得

今天主要内容是线程,感觉也并没有想象中的那么难,就是在龟兔赛跑的时候明明给兔子设置了高优先级,乌龟仍然能把兔子按地上锤,可能这就是玄学吧.明天加油!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值