深入Java线程(三)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wydyd110/article/details/86610214

接上文《深入Java线程(二)》

会猝死也要坚持学完

1 死锁(deadlock)问题

死锁:一组进程中,每个进程都无限等待被该组进程中 另一进程所占有的资源,因而永远无法得到的资源,这种现象称为 进程死锁,这一组进程就称为 死锁进程

银行家算法

仿照银行发放贷款时采取的控制方式而设计的 一种死锁避免算法

哲学家就餐问题

有五个哲学家围坐在一圆桌旁, 桌中央有一盘通心粉,每人面 前有一只空盘子,每两人之间 放一只筷子。每个哲学家的行为是思考,感 到饥饿,然后吃通心粉 为了吃通心粉,每个哲学家必 须拿到两只筷子,并且每个人 只能直接从自己的左边或右边去取筷子(筷子的互斥使用、 不能出现死锁现象)


可靠措施:

1 最多允许4个哲学家同时坐在桌子周围

2 仅当一个哲学家左右两边的筷子都可用时,才 允许他拿筷子

3 给所有哲学家编号,奇数号的哲学家必须首先 拿左边的筷子,偶数号的哲学家则反之

1.1 例子

创建3个线程模拟3个游戏者的行为

public class Main {
	public static void main(String[] args) {
		Balls ball = new Balls();
		
		Player0 p0 = new Player0(ball);
		Player1 p1 = new Player1(ball);
		Player2 p2 = new Player2(ball);
		
		p0.start();
		p1.start();
		p2.start();
	}
}

class Balls{
	//true表示已被拿走,false表示未被拿走
	boolean flag0 = false;
	boolean flag1 = false;
	boolean flag2 = false;
	
}

class Player0 extends Thread{
	private Balls ball;
	
	public Player0(Balls b) {this.ball = b;}
	
	public void run() {
		while(true) {
			while(ball.flag1==true) {}//若1号球已被拿走,则等待
			ball.flag1=true;
			while(ball.flag0==true) {}//若0号球已被拿走,则等待
			if(ball.flag1==true&&ball.flag0==false) {
				ball.flag0=true;
				System.out.println("Player0 has got two balls!");
				ball.flag1=false;//放下1号球
				ball.flag0=false;//放下0号球
				try {
					sleep(1); //放下后休息1ms
				} catch (InterruptedException e) {}
			}
		}
	}
}

class Player1 extends Thread{
	private Balls ball;
	
	public Player1(Balls b) {this.ball = b;}
	
	public void run() {
		while(true) {
			while(ball.flag0==true) {}//若0号球已被拿走,则等待
			ball.flag1=true;
			while(ball.flag2==true) {}//若2号球已被拿走,则等待
			if(ball.flag0==true&&ball.flag2==false) {
				ball.flag2=true;
				System.out.println("Player1 has got two balls!");
				ball.flag0=false;//放下0号球
				ball.flag2=false;//放下2号球
				try {
					sleep(1); //放下后休息1ms
				} catch (InterruptedException e) {}
			}
		}
	}
}

class Player2 extends Thread{
	private Balls ball;
	
	public Player2(Balls b) {this.ball = b;}
	
	public void run() {
		while(true) {
			while(ball.flag2==true) {}//若1号球已被拿走,则等待
			ball.flag2=true;
			while(ball.flag1==true) {}//若0号球已被拿走,则等待
			if(ball.flag2==true&&ball.flag1==false) {
				ball.flag1=true;
				System.out.println("Player0 has got two balls!");
				ball.flag2=false;//放下1号球
				ball.flag1=false;//放下0号球
				try {
					sleep(1); //放下后休息1ms
				} catch (InterruptedException e) {}
			}
		}
	}
}

运行结果

陷入死锁,没有输出信息

原因分析

因为若刚好3个人都拿到左边的球,都在等右边的球,因为谁都不愿放手,则陷入死锁

解决方案

2 线程的调度

2.1 线程优先级

1 每个Java线程都有一个优先级,1-10之间,默认设为5

2 线程A运行过程中创建线程B,A与B具有相同的优先级

3 可通过setPriority(int prioritt)设置优先级

4 具有相同优先级的线程,Java的处理是随机的

public class Main {
	public static void main(String[] args) {
		//构造一个线程数组
		TestThread[] runners = new TestThread[2];
		for(int i = 0; i < 2; i++)
			runners[i] = new TestThread(i);
		runners[0].setPriority(2);
		runners[1].setPriority(3);//优先级相对高
		
		for(int i = 0; i < 2; i++)
			runners[i].start();
	}
}

class TestThread extends Thread{
	private int tick = 1;
	private int num;
	
	public TestThread(int num) {
		super();
		this.num = num;
	}
	
	public void run() {
		while(tick < 200000) {
			tick++;
			if((tick % 50000)==0) {//每隔50000进行显示
				System.out.println("Thread #" + num +",tick="+tick);
				yield();//放弃执行权
			}
		}
	}
}

猜你喜欢

转载自blog.csdn.net/wydyd110/article/details/86610214