线程的基本操作:
1,新建线程:这个不用说了,通过继承Thread或者实现Runnable接口两种方式。
2,终止线程:一般来说,线程执行完毕就会结束,无须自动关闭。但是对于一些while true的线程如果想关闭呢?Thread类里有stop()方法,但是已经不建议使用了。因为它是强制停止线程,无论线程处于什么状态,很容易出现线程正在处理一半数据被停止的情况,这样非常容易造成数据不一致问题。所以慎用stop()(最好不用),通过下边这种方式来停止哪些无限循环的线程:
public class StopThread extends Thread {
volatile boolean stopme = false;
//停止方法
public void stopMe() {
stopme = true;
}
public void run() {
while (true) {
//死循环中如果出现停止标识,则直接跳出
if (stopme) {
System.out.println("exit by stop me");
break;
}
3,线程中断:是一种线程协作机制。是告诉目标线程一个中断通知,至于接到通知后如何处理,则有线程自己决定处理。
public class InterruptThread {
/**
* public void interrupt() 中断线程
* public static boolean interrupted() 判断是否被中断,并清除当前中断标识
* public boolean isInterrupted() 判断是否被中断
*/
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread() {
@Override
public void run() {
while (true) {
//判断如果有中断标识,则直接跳出
if (Thread.currentThread().isInterrupted()) {
System.out.println("exit by interrupted");
break;
}
System.out.println(System.currentTimeMillis());
Thread.yield();
}
}
};
t1.start();
Thread.sleep(2000);
//打上中断标识
t1.interrupt();
}
}
4,等待(wait)和通知(notify),也是为了支持线程之间的协作。方法都是在Object上定义的,例如线程A调用了obj.wiat()方法,那么线程A就会停止执行,等到其它线程调用obj.notify()方法为止。
public class WaitNotifyThread {
final static Object ob = new Object();
public static class T1 extends Thread {
public void run() {
synchronized (ob) {
System.out.println(System.currentTimeMillis() + "t1 is start");
try {
System.out.println(System.currentTimeMillis() + "t1 is wait");
ob.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(System.currentTimeMillis() + "t1 is end");
}
}
}
public static class T2 extends Thread {
public void run() {
synchronized (ob) {
System.out.println(System.currentTimeMillis() + "t2 is start");
System.out.println(System.currentTimeMillis() + "t2 is notify start");
ob.notify();
System.out.println(System.currentTimeMillis() + "t2 is notify end");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(System.currentTimeMillis() + "t2 is end");
}
}
}
public static void main(String[] args) {
Thread t1 = new T1();
Thread t2 = new T2();
t1.start();
t2.start();
}
}
5,挂起(suspend)和继续执行(resume):也是一对相对的操作,但是JDK也已经标示为废弃方法,不推荐使用。应为使用suspend()去挂起导致线程暂停的同时,并不释放资源,会阻塞其它线程,如果处理不当(例如resume()处理在suspend()之前了,就会导致一直阻塞),所以慎用。我们可以通过wait和notify来像实现stopMe()一样,实现自己一个挂起和继续执行操作。这里不再演示。
6,等待线程结束(join)和谦让(yield):类似现实生活中,我做这件事得等着它做完那件事,我为他让让步等。很容易理解的:
volatile:非常重要的关键字,如果用volatile修饰,虚拟机就会特殊处理,不能随意变动优化目标指令;并且修改后,各个线程都能看见它的改动,保证变量的可见性。在那个中共享变量是“一写多读”的情况下非常使用,保证修改及时可见。
线程组:非常容易理解的概念,如果线程过多,为了方便管理,有了线程组
线程安全和synchronized:线程安全就是针对共享资源能够高效有序的使用,不要出现同时修改,最终导致数据不一致的问题。而共享资源的同步使用即可解决。synchronized的作用就是实现线程间的同步。总结一下它的用法:1,指定加锁对象:给对象加锁,进入同步代码前要获得给定对象的锁:synchronized(obj);2,直接作用于实例方法:相当于对当前实例加锁,进入同步代码前要获得当前实例的锁:synchronized(this);3,直接作用于静态方法:相当于当前类加锁,进入同步代码前要获得当前类的锁。