Thread的常用方法
1.start()---线程调用该方法将启动线程,使之从新建状态进入就绪队列排队,结果是两个线程并发地运行;当前线程(从调用返回给 start 方法)和另一个线程(执行其 run 方法)。 一旦轮到它来享用CPU资源时,就可以脱离创建它的线程独立开始自己的生命周期了。
eg:
public class ThreadTest extends Thread{
public static void main(String[] args) {
Thread t = new Thread(new ThreadTest());
t.start();
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
System.out.println("Main is run!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
System.out.println("Thread is run!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
start方法起的线程和main方法线程并发执行。
2.run()---Thread类的run()方法与Runnable接口中的run()方法的功能和作用相同,都用来定义线程对象被调度之后所执行的操作,都是系统自动调用而用户程序不得引用的方法。
eg:
public class ThreadTest extends Thread{
public static void main(String[] args) {
Thread t = new Thread(new ThreadTest());
t.run();
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
System.out.println("Main is run!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
System.out.println("Thread is run!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
run方法并没有起线程而是在main方法线程里顺序执行。
3.stop()---已过时。该方法具有固有的不安全性。用 Thread.stop 来终止线程将释放它已经锁定的所有监视器(作为沿堆栈向上传播的未检查 ThreadDeath 异常的一个自然后果)。如果以前受这些监视器保护的任何对象都处于一种不一致的状态,则损坏的对象将对其他线程可见,这有可能导致任意的行为。stop 的许多使用都应由只修改某些变量以指示目标线程应该停止运行的代码来取代。目标线程应定期检查该变量,并且如果该变量指示它要停止运行,则从其运行方法依次返回。如果目标线程等待很长时间(例如基于一个条件变量),则应使用 interrupt 方法来中断该等待。
eg:
public class StopMain {
private static int j = 0 ;
public static void main(String[] args) {
Thread t = new Thread(){
@Override
public void run(){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
j++;
}
};
t.start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
t.stop();
System.out.println("j="+j);
}
}
stop方法强制中止线程,破坏了这个类的线程安全(也可以理解为破坏了数据的完整性)所以不建议在程序中使用stop()方法。
4.interrupt()---并不会立即执行中断操作;具体而言,这个方法只会给线程设置一个为true的中断标志(中断标志只是一个布尔类型的变量),而设置之后,则根据线程当前的状态进行不同的后续操作。如果,线程的当前状态处于非阻塞状态,那么仅仅是线程的中断标志被修改为true而已;如果线程的当前状态处于阻塞状态,还会有如下三种情况之一的操作:
- 1.如果线程在调用 Object 类的 wait()、wait(long) 或 wait(long, int) 方法,或者该类的 join()、join(long)、join(long, int)、sleep(long) 或 sleep(long, int) 方法过程中受阻,则其中断状态将被清除,它还将收到一个 InterruptedException。
- 2.如果该线程在可中断的通道上的 I/O 操作中受阻,则该通道将被关闭,该线程的中断状态将被设置并且该线程将收到一个 ClosedByInterruptException。
- 3.如果该线程在一个 Selector 中受阻,则该线程的中断状态将被设置,它将立即从选择操作返回,并可能带有一个非零值,就好像调用了选择器的 wakeup 方法一样。
eg:
public class InterruptMain {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(){
@Override
public void run(){
while(true){
if(Thread.currentThread().isInterrupted()){
System.out.println("break");
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) { //中止状态将被清除
System.out.println("Thead is sleep!");
Thread.currentThread().interrupt(); //重新设置下状态保证线程能够退出
e.printStackTrace();
}
Thread.yield();
}
}
};
t.start();
Thread.sleep(1000);
t.interrupt();
}
}
5.wait()和notify()---wait方法是Object对象的方法。任何对象都可以调用这个方法,可以中断方法的执行,使本线程等待,暂时让出CPU的使用权,在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。
notify方法是wait方法是Object对象的方法。任何对象都可以调用这个方法,通知处于等待中的线程的某一个结束等待。当有多个等待线程时候, 操作系统会根据一定的调度算法调度一个线程,当正在占有对象锁的线程释放锁的时候操作系统调度的这个线程就会执行。而而剩下的那些没有被notify的线程就不会获取执行机会。
eg:
public class WNTest {
final static Object o = new Object();
public static class T1 extends Thread{
@Override
public void run(){
synchronized(o){
System.out.println("T1 is start:"+System.currentTimeMillis());
try {
System.out.println("T1 is wait:"+System.currentTimeMillis());
o.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("T1 is end:"+System.currentTimeMillis());
}
}
}
public static class T2 extends Thread{
@Override
public void run(){
synchronized(o){
System.out.println("T2 is start:"+System.currentTimeMillis()+" start notify T1");
o.notify();
System.out.println("T2 is end:"+System.currentTimeMillis());
try {
Thread.sleep(1000); //不会释放锁,休眠1秒,T1获得对象锁才能进行执行。
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Thread t1 = new T1();
Thread t2 = new T2();
t1.start();
t2.start();
}
}
wait和sleep方法都可以让线程等待若干时间,区别:1.wait会被唤醒,2.wait会释放目标的对象锁
6.join()和yield()---join()方法在一个线程实例上调用,当前运行着的线程将阻塞直到这个线程实例完成了执行。yield()暂停当前正在执行的线程对象,并执行其他线程。
eg:
public class JTest {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(){
@Override
public void run(){
System.out.println("T1 is run!");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("T1 is over!");
}
};
Thread t2 = new Thread(){
@Override
public void run(){
System.out.println("T2 is run!");
}
};
t1.start();
t1.join();
t2.start();
}
}
public class YTest {
public static void main(String[] args) {
Thread t1 = new Thread(){
@Override
public void run(){
for (int i = 0; i < 5; i++) {
System.out.println("T1 is "+ i);
Thread.yield();
}
}
};
Thread t2 = new Thread(){
@Override
public void run(){
for (int i = 0; i < 5; i++) {
System.out.println("T2 is "+ i);
Thread.yield();
}
}
};
t1.setPriority(Thread.MIN_PRIORITY);
t2.setPriority(Thread.MAX_PRIORITY);
t1.start();
t2.start();
}
}