进程与线程
进程是一个程序的执行序列,在多任务的操作系统中,由操作系统调度并负责管理;线程是一个进程中的子序列,线程由程序负责管理。在多线程的环境下,线程共用相同的地址空间,线程之间的通信是非常方便的,它们共同构成了一个进程,而进程有不同的地址空间。进程与线程都是动态的概念。
进程与程序的区别是:进程是当程序执行时操作系统的一个调度,是动态的;程序是静态的。当程序执行时,得到操作系统的调度,形成操作系统的一个进程,依照程序的指令序列运行。
线程可以由程序负责管理,可以在程序中创建线程,启动线程,挂起线程,终止线程,将线程从程序中清除等操作。
Java利用多线程实现了整个执行环境是异步的。Java语言里,线程表现为线程类,线程类封装了所有需要的线程操作控制。
线程对象与运行线程的区别:可以将线程对象看作是运行线程的控制面板,在线程对象里有很多方法来控制一个线程是否运行,睡眠,挂起或停止。线程类是控制线程行为的唯一手段。一个Java程序启动后,就已经有一个线程在运行,可通过Thread.currentThread()方法来查看当前运行的是那一个线程。你得到一个线程的控制柄,就可以做很有趣的事情,即使单线程也一样。
线程的生命周期
Java线程从产生到灭亡,有以下几个状态:
新建状态(newborn):线程已被创建(线程对象已被分配了内存空间,私有数据已经被初始化)但还未执行这段时间,此时的线程可以被调度,变成可运行状态,也可以被杀死,变成停止状态。
就绪状态或可运行状态(Run able):线程正在等待CPU资源,随时可以被调度执行。这时线程已被调度,已被放在就绪队列中等待执行。至于该线程何时才被执行,取决于线程的优先级和就绪队列的当前状况。
运行状态(running):线程正在运行,该线程已经拥有了对CPU的控制权,让出CPU控制权的情况:
1, 线程运行完毕。
2, 有比当前线程优先级更高的线程处于可运行状态。
3, 线程主动睡眠一端时间。
4, 线程在等待某一资源。
挂起状态(blocked):这时的线程无法进入就绪队列。处于挂起状态的线程通常需要由某些事件才能唤醒,至于由什么事件唤醒该线程,取决于挂起的原因。
停止状态(dead):线程已经退出运行状态,并且不再进入就绪队列。其中的原因是可能线程已经执行完毕,也可能是被另外一个进程强行杀死。
线程的调度和优先级
调度:多个线程的并发执行实际上是通过一个调度程序来进行调度的。调度就是指在各个线程之间分配CPU资源。线程调度的两种模型——抢占式模型和分时模型。Java支持的是抢占式模型。因此,为了使低优先级的线程有机会运行,高优先级的线程应该不时地主动进入“睡眠”状态。
优先级:myThread.setPriority(i);I为1到10个级。
线程的同步和死锁
同步:多个线程同时访问(写入)同一资源。死锁:DB中讲的太多了吧!我不在这里废话了。
线程的创建
建立一个线程需要完成三件事:建立一个虚拟的CPU;给出线程的执行代码;提供代码所操作的数据。
在Java中,虚拟CPU是封装在Thread类中的。创建一个Thread对象,就相当于建立了一个虚拟的CPU。Java的面向对象模型要求为线程提供的代码和数据应该以类的实例形式存在。
第一:创建Thread类的子类
覆盖run()方法提供线程的执行代码,定义Thread类的成员变量来提供线程的数据。
package mythread;
public class MyThread extends Thread{
int mycount=1,mynumber;
public MyThread(int num) {
mynumber=num;
System.out.println("创建线程"+mynumber);
}
public void run(){
while(true){
System.out.println("线程"+mynumber+":记数"+mycount);
mycount++;
while(mycount==6)
return;
}
}
public static void main(String [] args){
for(int i=0;i<3;i++){
new MyThread(i + 1).start();
}
}
}
第二:实现Runnable接口
这是一个单方法接口。
public interface java.lang.Runnable{
public abstract void run();
}
将实现Runnable接口的一个类的实例作为参数传递给Thread类的构造器,创建了一个Thread类的实例,这个Thread类的实例将使用我们在自己类中实现的run()方法作为其执行代码,还可以使用我们定义的类的实例中的数据作为起操作的数据。
注意这里Runnable接口并没有任何对线程的支持(其实Thread也实现了它),还必须创建Thread类的实例。
public class TwoThread implements Runnable {
Thread mythread;
Int a;//定义我们要操作的数据
public TwoThread(int a) {
this.a=a;
}
public void start(){
mythread= new Thread(this);//把自己船进去后调用thread的start方法
mythread.start(); //start自动调用run方法
}
public void run() {
//这里写我们的处理代码
}
}
线程同步
Synchronized Java中有一个同步模型——监视器,负责管理线程对对象中的同步方法的访问,它的原理是:赋予该对象唯一一把钥匙,当多个线程进入对象,只有取得该对象钥匙的线程才可以访问同步方法,其他线程在该对象中等待,直到该线程用wait方法放弃这把钥匙,其他等待的线程抢占到该钥匙的线程后才得以执行,而没有取得钥匙的线程仍被阻塞在该对象中等待。通常可以用notify()或notigyAll()方法唤醒其他一个或所有线程。
线程间通信
管道流(pipe)用于在不同线程间直接传送数据。它有PipeInputStream和PipeOutputStream两个类支持。