多线程:控制线程

一、后台线程(守护线程)

守护线程,是指在程序运行的时候在后台提供一种通用服务的线程,比如JVM垃圾回收线程就是一个典型的守护线程,并且这种线程并不属于程序中不可或缺的部分。因此,当所有的非守护线程结束时,程序就没运行的必要了,程序也就终止了,同时会杀死进程中的所有守护线程。反过来说,只要任何非守护线程还在运行,程序就不会终止。

调用Thread对象的setDaemon(true)方法可以将该线程设置成后台线程。该方法必须在启动线程前调用。 

还有一个方法isDaemon()方法可以测试该线程是否为守护线程。

public class DaemonThread extends Thread {

	public static void main(String[] args) {
		DaemonThread thread = new DaemonThread();
		// 将此线程设置成后台线程
		thread.setDaemon(true);
		thread.start();
		for (int i = 0; i < 10; i++) {
			System.out.println(Thread.currentThread().getName() + i);
		}
	}

	@Override
	public void run() {
		for (int i = 0; i < 100; i++) {
			System.out.println(getName() + i);
		}
	}
}

运行结果:

...
Thread-0 10
main 9
Thread-0 11
...
Thread-0 32
Thread-0 33
...

可以看到当主线程运行完后,守护线程无法运行到循环变量100,可以判断出当非守护线程全部结束时,守护线程也会结束。

二、线程睡眠

通过调用Thread类的静态方法sleep(),可以在指定的毫秒数内让当前正在执行的线程阻塞(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。该线程不丢失任何监视器的所属权。

public class SleepTest {

	public static void main(String[] args) throws Exception {
		for(int i =0;i<10;i++) {
			System.out.println("当前时间:"+new java.util.Date());
			Thread.sleep(1000);
		}
	}

}

运行结果:

当前时间:Fri Sep 29 15:00:16 CST 2017
当前时间:Fri Sep 29 15:00:17 CST 2017
当前时间:Fri Sep 29 15:00:18 CST 2017

运行上面程序可以看到程序输出一次当前时间后,程序暂停一秒,然后再输出一次。

三、join线程

当在某个线程中调用其他线程的join()方法时,调用的线程会被阻塞,直到join线程执行完为止。

public class JoinThread extends Thread {
	public JoinThread(String name) {
		super(name);
	}

	@Override
	public void run() {
		for (int i = 0; i < 2; i++) {
			System.out.println(getName() + " " + i);
		}
	}

	public static void main(String[] args) throws Exception {
		for (int i = 0; i < 10; i++) {
			if (i == 3) {
				JoinThread jt = new JoinThread("执行join的线程");
				jt.start();
				jt.join();
			}
			System.out.println(Thread.currentThread().getName() + " " + i);
		}
	}
}

运行结果:

main 0
main 1
main 2
执行join的线程 0
执行join的线程 1
main 3
...

可以看到调用join()方法的主线程被阻塞,知道join线程执行完才开始执行下面的代码。

四、线程的优先级

每个线程执行时都具有一定的优先级,优先级高的线程会获得更多的执行机会,而优先级低的则较少。

每个线程默认的优先级与创建它的父线程的优先级相同,在默认情况下,main线程具有普通优先级(NORM_PRIORITY)。

Thread类提供了setPriority(int newPriority)、getPriority()方法来设置和返回指定线程的优先级,其中setPriority()方法的参数是一个整数,范围是1~10,也可以是下面的镜头常量。

Thread类有如下三个静态常量:

  • NORM_PRIORITY:其值是5
  • MIN_PRIORITY:其值是1
  • MAX_PRIORITY:其值是10
public class PriorityTest extends Thread {

	public PriorityTest(String name) {
		super(name);
	}

	public void run() {
		for (int i = 0; i < 10; i++) {
			System.out.println(getName() + ",其优先级是:" + getPriority() + ",循环变量的值为:" + i);
		}
	}

	public static void main(String[] args) {
		System.out.println("主线程的优先级:" + Thread.currentThread().getPriority());
		PriorityTest low = new PriorityTest("低优先级线程");
		PriorityTest high = new PriorityTest("高优先级线程");
		System.out.println(low.getName()+"创建之前的的优先级:"+low.getPriority());
		System.out.println(high.getName()+"创建之前的的优先级:"+high.getPriority());
		low.start();
		low.setPriority(MIN_PRIORITY);
		high.start();
		high.setPriority(MAX_PRIORITY);
	}
}

运行几次看到的结果都是high线程优先执行完的。

五、线程让步

yield()方法与sleep()方法相似,同样是Thread类的静态方法,也可以让当前线程暂停,但它不会阻塞该线程,而是将该线程转入就绪状态。yield()只是让当前线程暂停一下,让系统重新调度一次,所以很有可能重新执行原来的线程,而且该方法受优先级影响。

public class YieldTest extends Thread {

	@Override
	public void run() {
		for(int i=0;i<20;i++) {
			System.out.println(getName() + " " + i);
			if(i==5) {
				Thread.yield();
			}
		}
	}
	
	public static void main(String[] args) {
		YieldTest yt1 = new YieldTest();
		YieldTest yt2 = new YieldTest();
		yt1.start();
		yt2.start();
	}
}

运行结果:

...
Thread-1 4
Thread-0 5
Thread-1 5
Thread-0 6
...

程序开启两条优先级一样的线程,两个线程的循环变量i执行到5的时候,会发现线程会切换给另一个线程执行。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值