day_34Java多线程2

星期日, 十二月 06, 2015 17:49:26

四、线程的状态

4.1 概念

      任何一个线程一般都具有5种状态:

              创建、就绪、运行、阻塞、终止

在给定时间点上,一个线程只能处于一种状态

       1.new : 至今尚未启动的线程处于的状态

       2.runnable: 正在javav虚拟机中执行的线程

       3.blocked:受阻塞并等待某个监视器锁的线程

       4.waiting: 无限期的等待另一个线程来执行某一特定操作的线程

       5.timed_waiting:等待另一个线程来执行取决于指定等待时间的操作的线程

       6.te rminated:已退出的线程

4.2取得和设置线程的名称

             在Thread类中,可以通过getName()方法取得线程的名称,通过setName()方法设置线程的名称。

              线程的名称一般在启动线程前设置,但也允许为已运行的线程设置名称。

      允许两个Thread对象有相同的名字,但为了清晰,应该尽量避免这种情况的发生。

             另外,如果程序并没有为线程指定名称,系统会自动为线程分配名称。

4.2.1线程名称的分配

355--366  371 379  381

4.2.1代码案例:

package day34;

public class ThreadGetName extends Thread{
	
	public static void main(String[] args) {
		ThreadGetName tgn = new ThreadGetName();
		tgn.start();
		
		
		for(int i =0;i<3;i++) {
			tgn.printMsg();
		}
	}
	
	public void run() {
		for(int i=0;i<3;i++){
			printMsg();
		}
	}

	@SuppressWarnings("static-access")
	private void printMsg() {
		// TODO Auto-generated method stub
		//获得运行此代码的线程的引用
		Thread tn = new Thread();
		String name = tn.currentThread().getName();
		System.out.println("name --- "+name);
	}
	
	
}
运行结果:
name --- main
name --- main
name --- main
name --- Thread-0
name --- Thread-0
name --- Thread-0

 注意:

     1.main()方法也是一个线程,实际上在命令行运行java命令时,就启动了一个JVM的进程,

       默认情况下此进程会产生两个线程:

            1.一个是main()方法线程  2.一个就是垃圾回收(gc)线程

4.2.2在线程中设置线程的名称

代码案例:

package day34;

public class ThreadSetName extends Thread {
	public static void main(String[] args){
		@SuppressWarnings("unused")
		ThreadSetName tsn = new ThreadSetName();
		//设置线程的名称
		tsn.setName("test thread");
		tsn.start();
		
		for(int i=0;i<3;i++) {
			tsn.printMsg();
		}
		
	}
	
	public void run() {
		for(int i =0;i<3;i++) {
			printMsg();
		}
	}

	@SuppressWarnings("static-access")
	private void printMsg() {
		// TODO Auto-generated method stub
		Thread trd = new Thread();
		String name = trd.currentThread().getName();
		System.out.println("name---"+name);
	}
	
	
}
运行结果:
name---main
name---test thread
name---main
name---test thread
name---test thread
name---main

 4.3判断线程是否启动

     在程序中也可以通过isAlive()方法来测试线程是否已经启动而且仍然在启动。

package day34;

public class ThreadStartDemo extends Thread {
	public static void main(String[] args){
		@SuppressWarnings("unused")
		ThreadStartDemo tsn = new ThreadStartDemo();
		//设置线程的名称
		tsn.setName("test thread");
		System.out.println("在调用start()之前,tsn.isAlive() :"+tsn.isAlive());
		tsn.start();
		System.out.println("在调用start()时,tsn.isAlive() :"+tsn.isAlive());
		
		for(int i=0;i<3;i++) {
			tsn.printMsg();
		}
		//输出结果是不固定的,true/false
		System.out.println("main()结束时:"+tsn.isAlive());
	}
	
	public void run() {
		for(int i =0;i<3;i++) {
			printMsg();
		}
	}

	@SuppressWarnings("static-access")
	private void printMsg() {
		// TODO Auto-generated method stub
		Thread trd = new Thread();
		String name = trd.currentThread().getName();
		System.out.println("name---"+name);
	}
	
	
}

运行结果:
在调用start()之前,tsn.isAlive() :false
在调用start()时,tsn.isAlive() :true
name---main
name---main
name---main
main()结束时:true
name---test thread
name---test thread
name---test thread

 4.4后台线程与setDaemon()方法

    1.对java程序来说,只要还有一个前台线程在运行,这个进程就不会结束。

如果一个进程中只有后台线程在运行,这个进程就会结束。

    2.前台线程是相对后台线程而言的,前面所介绍的线程都是前台线程。

    3.后台线程:

          如果某个线程对象在启动(调用start()方法)之前调用了setDaemon(true)方法,

      这个线程就变成了后台线程。

看一下进程中只有后台线程在运行的情况。

4.4.1代码案例package day34;

public class ThreadSetDaemon {
	public static void main(String[] args) {
		TestThread ttd = new TestThread();
		Thread tt = new Thread(ttd);
		tt.setDaemon(true);//设置后台运行
     	tt.start();
	}
}
class TestThread implements Runnable {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(true) {
			System.out.println(Thread.currentThread().getName()+" is running");
		}
	}
	
}
运行结果:
Thread-0 is running
Thread-0 is running
Thread-0 is running
Thread-0 is running
....

 注意:

    从程序和运行结果中:

        1.创建了一个无限循环的线程,但因为它是后台线程,

          因此整个进程在主线程结束时就随之终止运行了。

        2.进行中只有后台线程运行时,进程就会结束。

4.5线程的强制运行

4.5.1 代码案例:

package day34;

public class ThreadJoin {
	public static void main(String[] args) {
		ThreadJ tj = new ThreadJ();
		Thread tr = new Thread(tj);
		tr.start();
		
		int i =0;
		for(int k=0;k<6;k++) {
			if(i == 5) {
				try {
					tr.join();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			System.out.println("main thread :"+(i++));
		}
	}
}
class ThreadJ implements Runnable {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		int i = 0;
		for(int j =0;j<6;j++){
			System.out.println(Thread.currentThread().getName()+" "+(i++));
		}
	}
	
}
运行结果:
main thread :0
main thread :1
main thread :2
main thread :3
main thread :4
Thread-0 0
Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-0 5
main thread :5

 注意:

    1.本程序两个线程main()和tj线程

    2.调用了tj线程的join()方法,join()是用来强制某一线程的运行。

总结:

    1.tj线程中的代码被并入到了main线程中,也就是main线程中的代码等待tj线程执行完。

4.6 线程的休眠

4.6.1代码案例

package day34;

public class ThreadSleep  extends Thread{
	public static void main(String[] args) {
		ThreadSleep ts = new ThreadSleep();
		ts.setName("my worker thread");
		ts.start();
		try {
			ts.sleep(700);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}ts.loop();
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		loop();
	}
	
	public void loop() {
		System.out.println("刚进入loop()方法:");
		for(int j =0;j<6;j++){
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName());
		}System.out.print("离开loop()方法:");
	}
	
}

 运行结果:

刚进入loop()方法:

刚进入loop()方法:

my worker thread

main

my worker thread

main

my worker thread

main

my worker thread

main

my worker thread

main

my worker thread

离开loop()方法:main

离开loop()方法:

速度慢了很多

4.7 线程的中断

   当一个线程运行时,另一个线程可以调用对应的Thread对象的interrupt()方法来中断它。

  

未实现

星期日, 十二月 06, 2015 21:45:39

猜你喜欢

转载自yuzhouxiner.iteye.com/blog/2262181