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。

Java并发编程--视频总结 02

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,让其他线程有更多的可能被执行

Java并发编程--视频总结 02

 例子:

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异常。

Java并发编程--视频总结 02

例子:

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;
			}
		}
	}
}
}