1.什么是线程?
Java中的线程是由CPU、代码、数据这三部分构成的,每个线程都是一个能独立执行自身指令的不同控制流,因此一个包含多线程的进程也能够实现多项任务的并发执行。系统在产生一个线程或在各个线程之间切换时,所占资源要比进程小的多,因此线程也被称为轻型进程;
线程可以定义为一个程序中的单个执行流,多线程是指一个程序中包含多个执行流,多线程是实现并发的一种有效手段;
线程是比进程更小的单位;
2.线程的创建
Java中的线程体是由线程类的run()方法声明,在该方法中定义线程的具体行为,线程开始执行时,也是从它的run()方法开始执行;
Thread类的构造方法有多个,这些方法发的一般语法为:
public Thread(ThreadGroup group,Runnable target,String name);
group指明该线程所属的线程组;
target提供线程体的对象;
name是线程名;
注:上述方法的每个参数都可以为null。
2-1.通过实现Runnable接口创建线程
在java.lang中Runnable接口的声明为:
public interface Runnable{
void run();
}
当实现Runnable接口的类的对象用来创建线程以后,该线程的启动将使得对象的run()方法被调用;新建的线程不会自动运行,必须调用线程的start()方法,例如,床垫一个线程t1,就必须用t1.start()来启动线程;
2-2.通过继承Thread类创建线程
Thread类本身实现了Runnable接口,所以在java.lang的Thread类的声明中可以发现run()方法;因此可以通过继承Thread类,并重写其中的run()方法定义线程,然后创建该子类的对象创建线程;
public class ThreadTest2{
public static void main(String args[]){
Hello t1 = new Hello();
t1.start();
}
}
class Hello extends Thread{
int i;
public void run(){
while(true){
System.out.println("Hello"+i++);
if(i==5) break;
}
}
}
3.线程优先级与线程调度策略
Java中的线程是有优先级的。MIN_PRIORITY待变最小优先级,通常为1;MAX_PRIORITY待变最小优先级,通常为10;NORM_PRIORITY待变最小优先级,通常为5;线程的优先级是MIN_PRIORITY和MAX_PRIORITY之间的一个值,并且数值越大,优先级越高;
在单个CPU上以某种顺序运行多个线程,称为线程的调度;
线程的基本控制:
(1)sleep()
该方法使一个线程暂停运行一段固定时间。在休眠时间内,线程将不运行,由于线程的调度是按照线程的优先级的高低顺序进行的,当优先级高的线程不结束时,优先级地的线程将没有机会获得CPU,高优先级线程可以在它的run()方法中调用sleep()来使自己退出CPU,休眠一段时间,休眠时间的长短由sleep()方法的参数决定,sleep()方法的格式是:
static void sleep(int millsecond):休眠时间以毫秒为单位。
(2)yield()
调用该方法后,可以使具有与当前线程相同优先级的线程有运行的机会。
如果有其他的线程与当前线程具有相同优先级并是可运行的,该方法将把调用yield()方法的线程放入可运行线程池,并允许其他线程运行。
(3)join()
t.join()方法是当前的线程等待,直到t结束为止,线程恢复到runnable状态。
(4)interrupt()
如果一个线程t在调用sleep()、join()、wait()等方法被阻塞时,则t.interrupt()方法将使t的终端状态被清除,中断t的阻塞状态,并且t将接收到InterruptException异常。
(5)currentThread()
返回当前线程的引用。
(6)isAlive()
isAlive()使用来测试线程确定是否还活着。
(7)stop()
用stop()方法强行终止线程,不提倡用这个方法,这方法容易导致线程的不一致;
(8)suspend()和resume()
在一个线程中调用t.suspend(),将使t暂停执行,要想恢复线程,就要由其他线程调用t.resume()回复t的执行,这个方法的缺点是用以导致线程的死锁。
线程间的交互:wait() 和 notify()
一个程序中单独的、并发的线程对同一个对象进行访问的代码段,称为临界区;
临界区可以是一个语句块或者是一个方法,并且用synchronized关键字标识;
Java平台将每一个由synchronized语句指定的对象设置一个锁,称为对象锁;
当线程进入synchronized块后,共享数据的状态并不满足它的需要,它需要等待其他线程将共享数据改变为它需要的状态后才能继续执行,但由于此时它占有了该对象的锁,其他线程无法对共享数据进行操作,所以引入了wait() 和 notify();
如果线程调用了某个对象X的wait()方法X.wait(),则该线程将放入X的wait pool,并且该线程将释放X的锁,当线程调用X的notify()方法X.notify()方法时,则对象的wait pool中的一个线程将移入lock pool,早lock pool中线程将等待X的锁,一旦获得便可运行。
notifyAll()把对象wait pool中的所有线程都移入lock pool;
因此,用wait() 和 notify()可以实现线程的同步。