控制线程

原创 2013年12月05日 22:55:32


1.join线程
在某条线程执行中调用其他线程的join()方法时,调用线程将被阻塞,直到被join方法加入的join线程完成为止。
join方法有三种重载的形式:
1)join():等待被join的线程执行完成。
2)join(long millis):等待被join的线程的时间最长为millis毫秒。如果在millis毫秒内,被join的线程还没有执行结束则不再等待。
3)join(long millis, int nanos):等待被join的线程的时间最长为millis毫秒加上nanos微妙。
见下面程序:
public class JoinThread extends Thread {
	
	//提供一个有参数的构造器,用于设置该线程的名字
	public JoinThread(String name){
		super(name);
	}
	//重写run方法,定义线程执行体
	public void run() {
		for(int i = 0; i < 100; i++){
			System.out.println(getName() + " " + i);
		}
	}

	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub

		//启动子线程
		new JoinThread("新线程").start();
		
		for(int i = 0; i < 100; i++) {
			if(i == 20) {
				JoinThread jt = new JoinThread("被join的线程");
				jt.start();
				//主线程调用了jt线程的join方法
				//主线程必须等jt执行结束才会向下执行
				jt.join();
			}
			System.out.println(Thread.currentThread().getName() + " " +i);
		}
	}

}

运行程序


程序中一共有3条线程,主方法开始时就启动了名为“新线程”的子线程,并与其并发执行。当主线程循环变量i等于20时,启动了名为“被join的线程”,该线程不会和主线程并发执行,而是主线程必须等该线程之行结束后才可以向下执行。


2.后台线程(Deamon Thread)
后台线程,即在后台运行的线程,它的任务是为其他的线程提供服务。JVM的垃圾回收线程就是典型的后台线程。后台线程有个特征:如果所有的前台线程都死亡,后台线程会自动死亡。调用Thread对象setDaemon(true)方法可将指定线程设置成后台线程。
public class DaemonThread extends Thread {
	//定义后台线程的线程执行体与普通线程没有任何区别
	public void run() {
		for(int i = 0; i < 1000 ; i++) {
			System.out.println(getName() + "------" + i);
		}
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		DaemonThread dt = new DaemonThread();
		//将此线程设置成后台线程
		dt.setDaemon(true);
		//启动后台线程
		dt.start();
		
		for(int i = 0; i < 10; i++) {
			System.out.println(Thread.currentThread().getName() + "------" + i);
		}
		//程序执行到此处,前台main线程结束
		//后台线程也随之结束
	}

}

运行程序

前台线程死亡后,JVM会通知后台线程死亡。但从后台接受命令到做出响应,需要一定时间。
后台线程t线程本来应该执行到i等于999时才会结束,但该后台线程无法运行到999,因为当唯一的前台线程主线程运行结束后,JVM会主动退出,因而后台线程也就被结束了。

注:要将某个线程设置为后台线程,必须在该线程启动之前设置,也就是setDaemon(true)必须在start()方法之前调用。否则会引发IllegalThreadStateException异常。


3.线程睡眠
当需要将当前正在执行的线程暂停一段时间,并进入阻塞状态,则可以通过调用Thread类的静态sleep方法。当当前线程调用sleep方法进入阻塞状态后,在其sleep时间段内,该线程不会获得执行的机会,即使系统中没有其他可运行的线程,处于sleep中的线程也不会运行。
public class TestSleep  {

	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub

		for(int i = 0; i < 5 ; i++) {
			System.out.println("当前时间:" + new Date());
			//调用sleep方法让当前线程暂停1s
			Thread.sleep(1000);
		}
	}
}

运行程序

输出每条字符串之间的时间间隔是1秒。

注:sleep()和wait()的异同
相同:都进入冻结状态,放弃执行资格,CPU会去执行其他线程
不同:sleep不会放弃锁;而wait会放弃锁。


4.线程让步
yeild()方法是Thread类提供的一个静态方法。它会让当前正在执行的线程暂停,但它不会阻塞该线程,它只是将该线程转入就绪状态。yield只是让当前线程暂停一下,让系统的线程调度器重新调度一次,完全可能的情况是:当某个线程调用了yield方法暂停之后,线程调度器又将其调度出来重新执行。
实际上,当某个线程调用了yield方法暂停之后,只有优先级与当前线程相同,或者优先级比当前线程更高的就绪状态的线程才会获得执行的机会。
public class TestYield extends Thread {
	
	public TestYield(){}
	
	public TestYield(String name){
		super(name);
	}
	//定义run方法作为线程执行体
	public void run() {
		for(int i = 0; i < 50; i++){
			System.out.println(getName() + " " + i);
			//当i等于20时,使用yield方法让当前线程让步
			if(i == 20) {
				Thread.yield();
			}
		}
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		//启动两条并发线程
		TestYield ty1 = new TestYield("高级");
		//将ty1线程设置成最高优先级
		//ty1.setPriority(Thread.MAX_PRIORITY);
		ty1.start();
		
		TestYield ty2 = new TestYield("低级");
		//将ty1线程设置成最高优先级
		//ty2.setPriority(MIN_PRIORITY);
		ty2.start();
	}

}

运行结果

当系统线程调度器重新调度时,由于两条线程的优先级完全一样,所以系统当一条线程使用yield方法暂停后,另一条线程就会开始运行。

如果将ty1.setPriority(Thread.MAX_PRIORITY);和ty1.setPriority(Thread.MIN_PRIORITY);两句代码的注释取消后,也就是为两条线程分别设置不同的优先级,程序运行结果:

低级线程执行到20调用yield后,让给高级线程执行。


5.改变线程优先级
每个线程执行时都具有一定优先级,优先级高的线程获得较多的执行机会,而优先级低的线程获得较少的执行机会。每个线程默认的优先级与创建它的父类具有相同的优先级,在默认情况下,主线程具有普通优先级,有主线程创建的子线程也有普通优先级。
Thread提供了setPriority(int newPriority)方法设置线程的优先级,参数可以是一个整数,范围是1-10之间。也可以使用Thread类的三个静态常量:
---->MAX_PRIORITY:其值是10。
---->MIN_PRIORITY:其值是5。
---->NORM_PRIORITY:其值是1。
public class PriorityTest extends Thread {
	
	public PriorityTest(){}
	//定义有参构造器,用于创建线程时指定name
	public PriorityTest(String name){
		super(name);
	}

	public void run() {
		for(int i = 0; i < 50; i++){
			System.out.println(getName() + ",其优先级是:" + getPriority() + ",循环变量是:" + i);
		}
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		//改变主线程的优先级
		Thread.currentThread().setPriority(6);
		for(int i = 0; i < 30; i++){
			if(i == 10) {
				PriorityTest low = new PriorityTest("低级");
				low.start();
				System.out.println("创建之初的优先级" + low.getPriority());
				//设置该线程为最低优先级
				low.setPriority(Thread.MIN_PRIORITY);
			}
			
			if(i == 20) {
				PriorityTest high = new PriorityTest("高级");
				high.start();
				System.out.println("创建之初的优先级" + high.getPriority());
				//设置该线程为最高优先级
				high.setPriority(Thread.MAX_PRIORITY);
			}
		}
	}

}

运行结果

可以看到优先级高的线程后的执行机会更多。


利用event控制线程同步.rar

  • 2007年09月03日 00:26
  • 172KB
  • 下载

java动态控制线程的启动和停止

最近项目有这样的需求:原来系统有个计算的功能,但该功能执行时间会很长(大概需要几个小时才能完成),如果执行过程中出现了错误的话,也只能默默的等待错误执行完成才行,无法做到动态的对该功能进行停止。 ...

动态控制线程执行和停止问题

  • 2016年02月23日 18:00
  • 10KB
  • 下载

QFuture 类 Qt 控制线程

QFuture类能够获取一个一步计算的结果。 通过使用这个  Qt Concurrent 框架内的一个api来开始一次计算。 它可以用允许多个线程同步一个或多个结果在稍后的一段时间内计算完成。这个结...

《疯狂Java讲义》——控制线程

join Thread类的join方法提供了让一个线程等待另一个线程完成的功能。 public class Test extends Thread { public Test(String ...

使用Condition控制线程通信

一.需求 实现线程间的通信,主线程循环3次后,子线程2循环2次,子线程3循环3次,然后主线程接着循环3次,如此循环3次. 即:A->B->C---A->B->C---A->B->C ...
  • lwj0310
  • lwj0310
  • 2014年04月25日 11:03
  • 301

控制线程(NSThread)和运行时循环(NSRunLoop)的退出

原文地址:http://shaheengandhi.com/controlling-thread-exit/ 这是讲iOS的线程的文章,下面的内容,自己都惨不忍睹啊,哈哈,练习翻译一下文章,...

Java多线程之控制线程

控制线程Java的线程支持,提供了便捷工具,方便控制线程的执行。包括join线程,后台线程,线程睡眠sleep,线程让步yield,改变线程优先级prioriy。join线程Thread提供了让一个线...

C++进阶—>CreateEvent控制线程

1.概述        事件对象就像一个开关:它只有两种状态---开和关。当一个事件处于”开”状态,我们称其为”有信号”否则称为”无信号”。可以在一个线程的执行函数中创建一个事件对象,然后观察它的状...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:控制线程
举报原因:
原因补充:

(最多只允许输入30个字)