多线程_callable_线程的状态_线程的停止_线程的阻塞(join,yield,sleep)_currentThread_priority_day30

1.使用callable接口实现多线程


我们继续用这个多线程来实现龟兔赛跑:

package callable;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * 我们用callable来模拟一下龟兔赛跑
 * 
 * @author Wang
 *
 */

public class Demo {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		ExecutorService ser = Executors.newFixedThreadPool(2);//这里就是创建两个线程
		
		Race tortoise = new Race("乌龟",1000);//1s走一步
		Race rabbit = new Race("小兔子",500);//0.5s
		
		Future<Integer> result1 =ser.submit(tortoise) ;//获取线程体返回过来的值   要用对应的类型进行接收
		Future<Integer> result2 =ser.submit(rabbit) ;
		
		Thread.sleep(2000); //2秒  让线程运行两秒
		tortoise.setFlag(false); //停止线程体循环
		rabbit.setFlag(false);
		
		int num1 =result1.get(); //注意这个地方要接收值
		int num2 =result2.get();
		System.out.println("乌龟跑了-->"+num1+"步");
		System.out.println("小兔子跑了-->"+num2+"步");
		//停止服务 
		ser.shutdownNow();//关闭线程
	}
}


class Race implements Callable <Integer> {//这里的Integer的作用是返回的是Interger类型的

	private String name;  //创建的这个线程叫什么名字
	private long time;    //多长时间走一步
	private boolean flag = true;//标志位
	private int step;//走了多少步
	
	public Race() {
		
	}
	
	public Race(String name, long time) {
		super();
		this.name = name;
		this.time = time;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public long getTime() {
		return time;
	}

	public void setTime(long time) {
		this.time = time;
	}

	public boolean isFlag() {
		return flag;
	}

	public void setFlag(boolean flag) {
		this.flag = flag;
	}

	public int getStep() {
		return step;
	}

	public void setStep(int step) {
		this.step = step;
	}

	@Override
	public Integer call() throws Exception {
		
		while(flag) {
			Thread.sleep(time);//程序睡眠多长时间  就是相当于多长时间走了一步
			step++;
		}
		return step;
	} 
	
} 

2.线程的状态:



2.线程的停止:


package Stop;
/**
 * 
 * 外部干涉来停止线程
 * 
 * @author Wang
 * 
 */

public class StopDemo01 {
	public static void main(String[] args) throws InterruptedException {
		run r = new run();//搞清楚谁是实体
		new Thread(r).start();//这里使用的是匿名类
		for(int i=0;i<30;i++) {
			if(i==10) {		//外部根据条件来调用停止对方法;		
				r.stop();
			}
			System.out.println(i);
		}
		
	}
}


class run implements Runnable{

	private boolean flag = true;//定义线程体中使用的标识
	
	@Override
	public void run() {
		while(flag) {//线程体使用该标识
			System.out.println("线程ing.....");
		}
	}
	
	void stop() {//提供外部的方法来改变标识
		flag = false;
		yi
	}
}
注意:其实Thread类(代理)里面也有线程停止的方法只不过这些方法,不推荐使用,主要是这些方法不安全;

3.线程的阻塞:

1.join():合并线程

package Stop;

/**
 * 
 * 线程的阻塞 Join
 * 
 * @author Wang
 *
 */

public class JoinDemo01 extends Thread {

	public static void main(String[] args) throws InterruptedException {
		JoinDemo01 j = new JoinDemo01();//新生
		Thread t = new Thread(j);
		t.start();//就绪
		//cpu运行调度
		
		for(int i=0;i<200;i++) {
			if(i==50) {
				t.join();//这里会把两个线程合为一个    会继续执行t但是变为了单线程   他执行玩以后在执行main()函数  所以我们就说main函数被阻塞;
			}
			System.out.println("main运行" + i);
		}

	}

	public void run() {// 重写run()方法 这个就是线程体
		for (int i = 0; i < 200; i++) {
			System.out.println("执行j" + i);
		}
	}
}

2.yield():暂停自己的线程    static

package Stop;
/**
 * 
 * 测试Yield
 * 
 * @author Wang
 *
 */

public class Yield extends Thread{
	public static void main(String[] args) {
		Yield y = new Yield();
		Thread t = new Thread(y);
		t.start();
		
		for(int i=0;i<50;i++) {
			if(i==10) {
				Thread.yield();//他是一个静态方法  在哪个线程里调用就会暂停那个线程  这个暂停只是暂停一瞬间
			}
			System.out.println("main" + i);
		}
	}
	
	public void run() {// 重写run()方法 这个就是线程体
		for (int i = 0; i < 100; i++) {
			System.out.println("执行y" + i);
		}
	}
}
3.sleep();睡眠  static,不释放锁(常用的方法)

one:与时间相关(模拟倒计时)

two:模拟网络延时

package Stop;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 
 * 测试一下sleep的用法
 * 
 * @author Wang
 *
 */

public class sleep {
	public static void main(String[] args)  throws InterruptedException {//写一个当前时间的倒计时
		Date endTime = new Date(System.currentTimeMillis()+10*1000);//得到倒计时的开始时间  当前时间10s后的时间 
		long end = endTime.getTime();
		
		while(true) {
			System.out.println(new SimpleDateFormat("mm:ss").format(endTime));//将这个时间格式化为字符串类型  采用了匿名类  这里给你所在的地区时间不太一致是牵涉到时区的问题
			Thread.sleep(1000);
			endTime = new Date(endTime.getTime() - 1000);
			
			if(end-10000 >= endTime.getTime()) {//倒计时10后跳出
				break;
			}
		}
		
	}
}

看一下网络延时给我们带来的问题:

package Stop;

import Runnable.Web;

/**
 * 
 * 来看一下网络延时所带来的问题
 * 
 * @author Wang
 *
 */

public class SleepDemo02 implements Runnable{
	private int ticketNum = 50;
	
	@Override
	public void run() {
		while(true) {
			if(ticketNum<0) {
				break;
			}
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "抢到了" + ticketNum--);
		}
		
	}
	
	public static void main(String[] args) {
		SleepDemo02 web = new SleepDemo02();//创建实体对象
		
		Thread thr1 = new Thread(web,"路人甲");//创建四个代理    他们来实现多线程的抢票
		Thread thr2 = new Thread(web,"黄牛");
		Thread thr3 = new Thread(web,"程序员");
		Thread thr4 = new Thread(web,"白领");
		
		
		thr1.start();
		thr2.start();
		thr3.start();
		thr4.start();
		
		
	}
}


从这张图上我们可以看到抢票抢到-1的情况

看这里当最后一次抢票的时候,这时候票还剩两张,我们第一个代理和第二个代理都会进去while()   但是他们会休眠所以num还是大于0的  不跳出循环  这样我们的另外两个代理都会进入程序中,就会拿到0和-1;

4.测试currentThread()

package priority;
/**
 * 
 * 自己写一个线程的实体
 * 
 * @author Wang
 *
 */

public class MyThread implements Runnable{

	private int num = 0;
	private boolean flag = true;
	
	@Override
	public void run() {
		while(flag) {
			System.out.println(Thread.currentThread().getName() + num++);//得到当前线程的名字;
		}
		
	}
	
	public void stop() {
		flag = false;
	}

}
package priority;
/**
 * 
 * 我们来测试一下这个类
 * 
 * @author Wang
 * 
 * Thread.currentThread()	 :当前线程
 * setName():设置名称
 * getName():获取名称
 * isAlive():判断状态
 *
 */

public class currentThread {
	
	public static void main(String[] args) throws InterruptedException {
		MyThread mt = new MyThread();//创建一个是实体
		
		Thread proxy = new Thread(mt,"wang");
		proxy.setName("wanga");//更改线程的名字
		System.out.println(proxy.getName());
		System.out.println(Thread.currentThread().getName());//获取当前线程的名字   在这里应该是Main
		
		proxy.start();
		
		System.out.println(proxy.isAlive());
		
		Thread.sleep(5);
	
		mt.stop();
		Thread.sleep(5);//  这里需要延时一下  给线程一个关闭的时间;
		
		System.out.println(proxy.isAlive());
		
		
	}

}

5.测试priority()

package priority;
/**
 * 
 * 我们来了解一下线程优先级的问题
 * 优先级:概率,不是绝对的先后顺序
 * MAX_PRIORITY  10
 * NORM_PRIORITY 5 (默认的优先级是这个)  
 * MIN_PRIORITY  1
 *  
 *  setPriority()
 *  getPriority()
 *  
 * @author Wang
 *
 */

public class PriorityDemo01 {
	public static void main(String[] args) throws InterruptedException {
		MyThread mt =new MyThread();
		Thread p1 =new Thread(mt,"aione");
		
		MyThread mt2 =new MyThread();
		Thread p2 =new Thread(mt2,"aitwo");
		
		p1.setPriority(Thread.MIN_PRIORITY); //设置优先级
		p2.setPriority(Thread.MAX_PRIORITY);//设置优先级    他的优先级高   那么他执行的概率就比较大
		p1.start();
		p2.start();
		
		
		
		Thread.sleep(1);
		mt.stop();
		mt2.stop();
	}
}

注意:我们学习java的基本知识就是学类和接口的;

         线程的优先级高  就是执行他的概率大一点   而不是先执行优先级高的  在执行优先级低的;


猜你喜欢

转载自blog.csdn.net/qq_38053395/article/details/80652226