Java并发编程--视频总结 02
线程的基本操作
新建线程
两种方式:向Thread类构造函数传递一个Runnable,或者直接重写Thread中的run方法(包括继承重写)。调用Thread类的start方法开始执行一个线程的任务。
示例:
package day_3_8;
public class ThreadCreation {
public static void main(String[] args) {
Thread t=new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<10;i++)
System.out.println("use a Runnable and Thread");
}
});
Thread t2=new ThreadCreation().new InnerThread();
t.start();
t2.start();
for(int i=0;i<10;i++)
System.out.println("this is main thread");
}
class InnerThread extends Thread{
@Override
public void run() {
for(int i=0;i<10;i++)
System.out.println("override a run function");
}
}
}
终止线程
Thread.stop() 不推荐使用。它会释放所有monitor(monitor可以类比为一个特殊的房间,这个房间中有一些被保护的数据,monitor保证每次只能有一个线程能进入这个房间进行访问被保护的数据,进入房间即为持有monitor,退出房间即为释放monitor。)。
中断线程
public void Thread.interrupt() // 中断线程
public boolean Thread.isInterrupted() // 判断是否被中断
public static boolean Thread.interrupted() // 判断是否被中断,并清除当前中断状态
例子:
package day_3_8;
public class ThreadInterrupt {
public static void main(String[] args) {
Thread1 thread1=new Thread1();
thread1.start();
for(int i=0;i<10000;i++) {
System.out.println("thread main is running");
}
thread1.interrupt();
System.out.println("end!");
}
}
class Thread1 extends Thread{
public void run() {
while(true) {
System.out.println("Thread1 running...");
if(Thread.currentThread().isInterrupted()) {
System.out.println("Thread1 is interrupted!");
break;
}
}
};
}
public static native void sleep(long millis) throws InterruptedException睡眠时被中断会抛出InterruptedException异常,并且会重置中断标志。
例子:
package day_3_8;
public class ThreadInterrupt {
public static void main(String[] args) {
Thread1 thread1=new Thread1();
thread1.start();
for(int i=0;i<10000;i++) {
System.out.println("thread main is running");
}
thread1.interrupt();
Thread2 thread2=new Thread2();
thread2.start();
thread2.interrupt();
System.out.println("end!");
}
}
class Thread1 extends Thread{
public void run() {
while(true) {
System.out.println("Thread1 running...");
if(Thread.currentThread().isInterrupted()) {
System.out.println("Thread1 is interrupted!");
break;
}
}
};
}
class Thread2 extends Thread{
public void run() {
while(true) {
if(Thread.currentThread().isInterrupted()) {
System.out.println("Thread2 is interrupted!");
break;
}
try {
Thread.sleep(1000);
}catch(InterruptedException e) {
System.out.println("interrupted tag is been cleared");
Thread.currentThread().interrupt();//重新设置中断标志
}
}
};
}
挂起(suspend)和继续执行(resume)线程
不推荐使用 suspend() 去挂起线程的原因,是因为 suspend() 在导致线程暂停的同时,并不会去释放任何锁资源。其他线程都无法访问被它占用的锁。直到对应的线程执行 resume() 方法后,被挂起的线程才能继续,从而其它被阻塞在这个锁的线程才可以继续执行。
但是,如果 resume() 操作出现在 suspend() 之前执行,那么线程将一直处于挂起状态,同时一直占用锁,这就产生了死锁。而且,对于被挂起的线程,它的线程状态居然还是 Runnable。
package day_3_8;
public class SuspendAndResume {
public static Integer i=0;
public static void main(String[] args) throws Exception {
Thread_this this1=new Thread_this();
Thread_local local=new Thread_local();
this1.start();
local.start();
Thread.currentThread().sleep(1000);
this1.suspend();
}
}
class Thread_this extends Thread{
@Override
public void run() {
synchronized (SuspendAndResume.i) {
while(true) {
SuspendAndResume.i++;
System.out.println("Thread_this"+SuspendAndResume.i);
// Thread.currentThread().resume();//resume在suspend执行之前执行
}
}
}
}
class Thread_local extends Thread{
@Override
public void run() {
synchronized (SuspendAndResume.i) {
while(true) {
SuspendAndResume.i++;
System.out.println("Thread_local"+SuspendAndResume.i);
}
}
}
}
等待线程结束(join)和谦让(yeild)
public final void join() throws InterruptedException
public final synchronized void join(long millis) throws InterruptedException
public static native void yield()//让出cpu,让其他线程有更多的可能被执行
例子:
package day_3_8;
public class WaitAndJoin {
public static void main(String[] args) throws Exception {
SimpleCounter simpleCounter=new SimpleCounter();
simpleCounter.start();
simpleCounter.join();//会等待该线程执行完
System.out.println("Thread main is running...");
}
}
class SimpleCounter extends Thread{
@Override
public void run() {
for(int i=0;i<1000000;i++) {
System.out.println(i);
}
}
}
守护线程
在后台默默地完成一些系统性的服务,比如垃圾回收线程、 JIT线程就可以理解为守护线程
当一个Java应用内,只有守护线程时,Java虚拟机就会自然退出
例子:
package day_3_8;
public class Daemon {
public static void main(String[] args) {
Thread_daemon daemon=new Thread_daemon();
daemon.setDaemon(true);
daemon.start();
for(int i=0;i<100000;i++) {
System.out.println(i);
}
}
}
class Thread_daemon extends Thread{
@Override
public void run() {
while(true){
System.out.println("Thread_daemon is running");
}
}
}
线程优先级
java 中的线程优先级的范围是1~10,默认的优先级是5。“高优先级线程”会优先于“低优先级线程”执行。
/**
* The minimum priority that a thread can have.
*/
public final static int MIN_PRIORITY = 1;
/**
* The default priority that is assigned to a thread.
*/
public final static int NORM_PRIORITY = 5;
/**
* The maximum priority that a thread can have.
*/
public final static int MAX_PRIORITY = 10;
基本的线程同步操作
synchronized
– 指定加锁对象:对给定对象加锁,进入同步代码前要获得给定对象的锁。
– 直接作用于实例方法:相当于对当前实例加锁,进入同步代码前要获得当前实例的锁。
– 直接作用于静态方法:相当于对当前类加锁,进入同步代码前要获得当前类的锁。
object.wait()和object.notify()和object.notifyall()
void wait(long millis)和void wait(long millis,int nanos)
导致线程进入等待状态直到它被通知或者经过指定的时间。这些方法只能在同步方法中调用。如果当前线程不是锁的持有者,该方法抛出一个IllegalMonitorStateException异常。
void notifyAll()
解除所有那些在该对象上调用wait方法的线程的阻塞状态。该方法只能在同步方法或同步块内部调用。如果当前线程不是锁的持有者,该方法抛出一个IllegalMonitorStateException异常。
void notify()
随机选择一个在该对象上调用wait方法的线程,解除其阻塞状态。该方法只能在同步方法或同步块内部调用。如果当前线程不是锁的持有者,该方法抛出一个IllegalMonitorStateException异常。
例子:
package day_3_8;
public class WaitAndNotify {
public static void main(String[] args) throws Exception {
Object obj=new Object();
WaitThread1 thread1=new WaitThread1();
WaitThread2 thread2=new WaitThread2();
thread1.setObj(obj);
thread2.setObj(obj);
thread1.start();
thread2.start();
// synchronized (obj) {
// obj.notify();
// }
Thread.sleep(10000);
synchronized (obj) {
System.out.println("notifyAll...唤醒全部");
obj.notifyAll();
}
}
}
class WaitThread1 extends Thread{
private Object obj;
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
@Override
public void run() {
int i=0;
synchronized (obj) {
while(true) {
System.out.println("WaitThread1 running");
if(++i==10) {
try {
obj.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(i>20) {
break;
}
}
}
}
}
class WaitThread2 extends Thread{
private Object obj;
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
@Override
public void run() {
int i=0;
synchronized (obj) {
while(true) {
System.out.println("WaitThread2 running");
if(++i==10) {
try {
obj.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(i>20) {
break;
}
}
}
}
}