`

JAVA基础_线程

阅读更多
1. 程序、进程、线程概念
程序:是计算机指令的集合,它以文件的形式存储在磁盘上。

进程:是程序运行的一个实例,是程序在自己的地址空间上的一次执行。

线程:是程序中一个单一的顺序控制流程。

通常的程序是不能并发执行的。为了使程序能够独立运行,应该为之配置一些进程控制块,即PCB;而由程序段,相关数据段和PCB三部分构成了进程实体。通常我们并不区分进程和进程实体,基本上就代表同一事物。进程是资源申请、调度和独立运行的单位,因此,它使用系统中的运行资源;而程序不能申请系统资源,不能被系统调度,也不能作为独立运行的单位,因此,它不占用系统的运行资源。

2. 线程的生命周期
新建状态:用new语句创建的线程对象处于新建状态,此时它和其它的java对象一样,仅仅在堆中被分配了内存

就绪状态:当一个线程创建了以后,其他的线程调用了它的start()方法,该线程就进入了就绪状态。处于这个状态的线程位于可运行池中,等待获得CPU的使用权

运行状态:处于这个状态的线程占用CPU,执行程序的代码

阻塞状态:当线程处于阻塞状态时,java虚拟机不会给线程分配CPU,直到线程重新进入就绪状态,它才有机会转到运行状态。

阻塞状态分为三种情况:
2.1、 位于对象等待池中的阻塞状态:当线程运行时,如果执行了某个对象的wait()方法,java虚拟机就回把线程放到这个对象的等待池中
2.2、 位于对象锁中的阻塞状态,当线程处于运行状态时,试图获得某个对象的同步锁时,如果该对象的同步锁已经被其他的线程占用,JVM就会把这个线程放到这个对象的琐池中。
2.3、 其它的阻塞状态:当前线程执行了sleep()方法,或者调用了其它线程的join()方法,或者发出了I/O请求时,就会进入这个状态中。

wait()和sleep的区别
sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。
wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。


死亡状态:当线程运行结束或者异常结束。

线程状态转换图:


3. 线程的创建及启动
   继承 Thread类与实现Runnable接口。启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。run()方法可以产生必须退出的标志来停止一个线程。
实现Runnable接口的线程:
package thread;

public class NewThreadRuabble implements Runnable{

	public Thread t;
	
	public NewThreadRuabble(String threadName){
		t = new Thread(this, threadName);
		System.out.println("child NewThreadRuabble----:"+t);
		t.start();
	}
	@Override
	public void run() {
		try{
			for(int i=5; i>0; i--){
				System.out.println("child thread----:"+i);
				Thread.sleep(1000);
			}
		}
		catch(InterruptedException e){
			System.out.println("--InterruptedException:"+e);
		}
		System.out.println("--exit child thread");
	}

}

继承Thread的线程:
package thread;

public class NewThreadThread extends Thread{
	
	public NewThreadThread(String name){
		super(name);
		System.out.println("Child NewThreadThread:"+this);
//		
//		start();
	}

	
	public void run() {
		try{
			for(int i=5; i>0; i--){
				System.out.println("child thread----:"+i);
				Thread.sleep(1000);
			}
		}
		catch(InterruptedException e){
			System.out.println("--InterruptedException:"+e);
		}
		System.out.println("--exit child thread");
	}
}



4. 线程的挂起和恢复
  一但线程开始执行run方法,就会一直到这个run方法执行完成这个线程才退出。但在线程执行的过程中,可以通过suspend。在使用suspend挂起线程后,可以通过resume方法唤醒线程。
虽然suspend和resume可以很方便地使线程挂起和唤醒,但由于使用这两个方法可能会造成一些不可预料的事情发生,调用suspend后,线程不释放对象锁和资源,容易导致多个线程互相等待释放资源,从而引起死锁。所以不推荐使用suspend和resume方法。可以用wait(),notify(),notifyAll()来实现线程的挂起和恢复。见线程的信号灯机制

5. 线程的结束
线程有stop()方法终止线程,但是从来都不使用它,因为它不安全。它会解除由线程获取的所有锁定,而且如果对象处于一种不连贯状态,那么其他线程能在那种状态下检查和修改它们。结果 很难检查出真正的问题所在。而且使用stop()方法会导致抛出ThreadDeath错误。 ThreadDeath继承了java.lang.Error,可见使用stop()的严重性。
可以使用线程的信号灯机制控制线程结束。

6. 线程的信号灯机制
简单的说,就是用同步控制一个状态,状态为true的时候,继续执行,为false的时候继续等待,只到其他线程对该对象调用notify()和notifyAll().
package thread;

class SuspendFlag implements Runnable{
	String name;
	Thread t;
	boolean suspendFlag; //线程线号灯
	
	SuspendFlag(String threadname){
		name = threadname;
		t = new Thread(this, name);
		System.out.println("New SuspendFlag: " + t);
		suspendFlag = false;
		t.start();
	}
	
	public void run() {
		try{
			for(int i = 15; i> 0; i--){
				System.out.println(name +": "+ i);
				Thread.sleep(200);
				synchronized(this){
					while(suspendFlag)wait();
				}
			}
		}
		catch(Exception e){
			
			System.out.println(name + " interrupted.");
			
		}
		System.out.println(name + " exiting.");
	}
	
	synchronized void mySuspend(){
		suspendFlag = true;
	}
	
	synchronized void myResume(){
		suspendFlag = false;
		notify();
	}
}

class SuspendResumeFlag{
	
	
	public static void main(String[] args) {
		SuspendFlag ob1 = new SuspendFlag("One");
		SuspendFlag ob2 = new SuspendFlag("Two");
		double f = 3.4;
		try{
			Thread.sleep(1000);
			ob1.mySuspend();
			System.out.println(" Suspending thread One.");
			Thread.sleep(1000);
			ob1.myResume();
			System.out.println(" Resuming thread One.");
			ob2.mySuspend();
			System.out.println(" Suspending thread Two.");
			Thread.sleep(1000);
			ob2.myResume();
			System.out.println(" Resuming thread Two.");
		}
		catch(Exception e){
			
			System.out.println("Main thread interrupted.");
			
		}
		try{
			System.out.println("Waiting for thread to finish.");
			ob1.t.join();
			ob2.t.join();
		}
		catch(Exception e){
			
			System.out.println("Main thread interrupted.");
			
		}
		System.out.println("Main thread exiting.");
		
	}
}


7. 线程的同步

7.1. 同步和异步的概念

同步用于共享资源的独占,也就是一资源在一个时间点只能被一个对象独占。比如打印机,一次只能打印一个文档,其他文档不可以打印,否则打印的内容会混乱。比如写文档,一个文档一次只能由一人来写入,否则文档内容没有可读性。

异步可以认为一资源在一个时间点可以被多个对象共享。比如读一个文档,可以多个人来读。

可以将同步想象成一次只能由一俩车通行的车道。异步是多车道。

7.2. 线程的同步

实现线程的同步有两种方法。 synchronized() 和 wait() 与 notify()。
  • 大小: 49.4 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics