如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:
1 (Thread.MIN_PRIORITY ) - 10 (Thread.MAX_PRIORITY ) NORM_PRIORITY(5)
步骤:
代码实现
package com.ljw.thread; public class RunnableDemo { public static void main(String[] args) { // 测试 RunnableDemo R = new RunnableDemo(); RunnableThread R1 = R.new RunnableThread("thread1"); R1.start(); RunnableThread R2 = R.new RunnableThread("thread2"); R2.start(); } class RunnableThread implements Runnable{ private String threadName; private Thread t; public RunnableThread(String name) { // TODO Auto-generated constructor stub threadName = name; System.out.println("创建线程 "+threadName); } @Override public void run() { System.out.println("正在运行线程:"+threadName); try { for(int i=10;i>0;i--) { System.out.println("线程:"+threadName+" 正在打印:"+i); Thread.sleep(50); } }catch(Exception e) { e.printStackTrace(); } System.out.println("线程:"+threadName+" 正在退出......"); } public void start() { System.out.println("开始线程 "+threadName); if(t == null) { t = new Thread(this, threadName); t.start(); } } } }
步骤:
步骤:
Callable接口与Runnable接口的区别:
代码实现
package com.ljw.thread; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; public class CallableThreadTest implements Callable<Integer> { public static void main(String[] args) { CallableThreadTest ctt = new CallableThreadTest(); FutureTask<Integer> ft = new FutureTask<>(ctt); for(int i = 0;i < 10;i++) { System.out.println(Thread.currentThread().getName()+" 的循环变量i的值"+i); if(i%2==0) { new Thread(ft,"有返回值的线程").start(); } } try { System.out.println("子线程的返回值:"+ft.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } @Override public Integer call() throws Exception { int i = 0; for(;i<10;i++) { System.out.println(Thread.currentThread().getName()+" "+i); } return i; } }
synchronized方法
或者 synchronized代码块
时,其他线程对该对象的该 synchronized方法
或者 synchronized代码块
的访问将被阻塞。 synchronized方法
或者 synchronized代码块
时,其他线程仍然可以访问该对象的非同步代码块。 synchronized方法
或者 synchronized代码块
时,其他线程对该对象的其他的 synchronized方法
或者 synchronized代码块
的访问将被阻塞。 两个相似的例子
package com.ljw.thread; public class RunnableTest { public static void main(String[] args) { class MyRunnable implements Runnable{ @Override public void run() { synchronized (this) { for(int i=0;i<5;i++) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " 正在进行打印 " +i); } } } } Runnable runnable = new MyRunnable(); Thread t1 = new Thread(runnable,"t1"); Thread t2 = new Thread(runnable,"t2"); t1.start(); t2.start(); } }
运行结果: ``` t1 正在进行打印 0 t1 正在进行打印 1 t1 正在进行打印 2 t1 正在进行打印 3 t1 正在进行打印 4 t2 正在进行打印 0 t2 正在进行打印 1 t2 正在进行打印 2 t2 正在进行打印 3 t2 正在进行打印 4 ``` 结果说明:run()方法中存在synchronized(this)代码块,而且t1和t2都是基于MyRunnable这个Runnable对象创建的线程。这就意味着,我们可以将synchronized(this)中的this看做是MyRunnable这个Runnable对象;因此,线程t1和t2共享“MyRunable对象的同步锁”。所以,当一个线程运行的时候,另外一个线程必须等待正在运行的线程释放MyRunnable的同步锁之后才能运行。 - 实例2:继承Thread类 ```java public class ThreadTest { public static void main(String[] args) { class MyThread extends Thread{ public MyThread(String name){ super(name); } @Override public void run() { synchronized(this){ for(int i=0;i<10;i++){ try { Thread.sleep(100); System.out.println(Thread.currentThread().getName()+" 正在进行打印 "+i); } catch (InterruptedException e) { e.printStackTrace(); } } } } } Thread t1 = new MyThread("t1"); Thread t2 = new MyThread("t2"); t1.start(); t2.start(); } } ``` 运行结果: ``` t2 正在进行打印 0 t1 正在进行打印 0 t2 正在进行打印 1 t1 正在进行打印 1 t1 正在进行打印 2 t2 正在进行打印 2 t2 正在进行打印 3 t1 正在进行打印 3 t1 正在进行打印 4 t2 正在进行打印 4 ``` 对比结果:发现实例1的两个线程是一个结束后,另一个才运行,实例2的是交叉运行,在run()方法中都有synchronized(this),为什么结果不一样? 分析:**synchronized(this)**中的**this**是指**当前对象**,即synchronized(this)所在类对应的当前对象。它的作用是获取获取当前对象的同步锁。对于**实例2**中的synchronized(this)中的**this**代表的是**MyThread对象**,t1和t2是两个**不同的MyThread对象**,因此t1和t2在执行synchronized(this)时获取的是不同对象的同步锁。对于**实例1**来说,synchronized(this)中的**this**代表的时候**MyRunnable对象**,**t1**和**t2**是**共同**一个**MyRunnable对象**,因此,一个线程获取了对象的同步锁,会造成另一个线程的等待。
synchronized方法 synchronized代码块
public class SnchronizedTest { public static void main(String[] args) { class Demo { // synchronized方法 public synchronized void synMethod() { for(int i=0; i<1000000; i++) ; } public void synBlock() { // synchronized代码块 synchronized( this ) { for(int i=0; i<1000000; i++) ; } } } } }
pulbic class Something { public synchronized void isSyncA(){} public synchronized void isSyncB(){} public static synchronized void cSyncA(){} public static synchronized void cSyncB(){} }
假设,类Something有两个实例(对象)分别为x和y。分析下面4组表达式获取锁的情况。
x.isSyncA()与x.isSyncB()
x.isSyncA()与y.isSyncA()
x.cSyncA()与y.cSyncB()
x.isSyncA()与Something.cSyncA()
package com.ljw.thread; public class WaitDemo { public static void main(String[] args) { class ThreadTest extends Thread{ @Override public void run() { synchronized (this) { System.out.println("开始运行线程 "+Thread.currentThread().getName()); System.out.println("唤醒线程notify()"); notify(); } } } ThreadTest thread1 = new ThreadTest(); thread1.start(); synchronized (thread1) { try { System.out.println("主线程进入阻塞,释放thread对象的同步锁,wait()"); thread1.wait(); // wait()是让当前线程进入阻塞状态,wait()是在主线程中执行, } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("主线程继续进行"); } }
package com.ljw.thread; public class YieldTest { public static void main(String[] args) { class ThreadA extends Thread{ public ThreadA(String name){ super(name); } @Override public synchronized void run() { for(int i=0;i<5;i++){ System.out.println(" "+this.getName()+" "+i); if(i%2 == 0){ Thread.yield(); } } } } ThreadA t1 = new ThreadA("t1"); ThreadA t2 = new ThreadA("t2"); t1.start(); t2.start(); } }
运行结果(不唯一):
t1 0 t2 0 t1 1 t1 2 t2 1 t1 3 t2 2 t1 4 t2 3 t2 4
结果说明:
线程t1在能被2整除的时候,并不一定切换到线程2。这表明,yield()方法虽然可以让线程由“运行状态”进入到“就绪状态”;但是,它不一定会让其他线程获取CPU执行权(其他线程进入到“运行状态”)。即时这个“其他线程”与当前调用yield()的线程具有相同的优先级。
@Override public void run() { try { // 1. isInterrupted()保证,只要中断标记为true就终止线程。 while (!isInterrupted()) { // 执行任务... } } catch (InterruptedException ie) { // 2. InterruptedException异常保证,当InterruptedException异常产生时,线程被终止。 } }
public class InterruptBlock { /** * @param args */ public static void main(String[] args) { class MyThread extends Thread{ public MyThread(String name){ super(name); } @Override public void run() { try { int i=0; while(!isInterrupted()){ Thread.sleep(100); i++; System.out.println(Thread.currentThread().getName()+ " ("+this.getState()+") loop "+i); } } catch (InterruptedException e) { e.printStackTrace(); System.out.println(Thread.currentThread().getName()+ " ("+this.getState()+") catch InterruptedExecption"); } } } try { //新建 Thread t1 = new MyThread("t1"); System.out.println(t1.getName()+" ("+t1.getState()+" ) is new."); System.out.println("luo1:"+t1.isInterrupted()); //启动 t1.start(); System.out.println(t1.getName()+" ("+t1.getState()+" ) is started."); System.out.println("luo2:"+t1.isInterrupted()); //主线程休眠300ms,然后主线程给t1发“中断”指令 Thread.sleep(300); t1.interrupt(); System.out.println("luo3:"+t1.isInterrupted()); System.out.println(t1.getName()+" ("+t1.getState()+" ) is interrupted."); //主线程休眠300ms,然后查看t1的状态 Thread.sleep(300); System.out.println(t1.getName()+" ("+t1.getState()+" ) is interrupted now ."); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
运行结果:
t1 (NEW ) is new. luo1:false t1 (RUNNABLE ) is started. luo2:false t1 (RUNNABLE) loop 1 t1 (RUNNABLE) loop 2 luo3:true t1 (RUNNABLE) loop 3 t1 (RUNNABLE ) is interrupted. t1 (TERMINATED ) is interrupted now .
package com.ljw.thread; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolDemo { public static void main(String[] args) { // 主线程 // 线程池 ---> Executors工具类(工厂类) /* * newFixedThreadPool(int threadCount) 创建固定数量的线程池 * newCachedThreadPool() 创建动态数量的线程池 */ ExecutorService es = Executors.newFixedThreadPool(3); Runnable task = new MyTask(); // 提交任务 es.submit(task); es.submit(task); es.shutdown(); // 关闭线程池,则表示不在接收新任务,不代表正在线程池的任务会停掉 } } class MyTask implements Runnable{ @Override public void run() { for(int i=0;i<100;i++) { System.out.println(Thread.currentThread().getName()+" MyTask "+i); } } }
package com.ljw.thread; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; /** * ReentrantLock类,重入锁:Lock接口的实现类,与synchronized一样具有互斥锁功能 lock() 和 unlock() * ReentrantReadWriteLock类,读写锁:一种支持一写多读的同步锁,读写分离,分别分配读锁和写锁,在读操作远远高于写操作的环境中可以提高效率 * 互斥规则: * 写--写:互斥,阻塞 * 读--写:互斥,阻塞 * 读--读:不互斥,不阻塞 * */ public class LockDemo { public static void main(String[] args) { ExecutorService es = Executors.newFixedThreadPool(20); Student s = new Student(); // ReentrantLock rLock = new ReentrantLock(); // 用ReenTrantLock加锁运行时间20008ms ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); // 用读写锁分别对读写任务加锁运行时间3003ms ReadLock rl = rwLock.readLock(); WriteLock wl = rwLock.writeLock(); // 写任务 Callable<Object> writeTask = new Callable<Object>() { @Override public Object call() throws Exception { // rLock.lock(); wl.lock(); try { Thread.sleep(1000); s.setValue(100); }finally { // rLock.unlock(); wl.unlock(); } return null; }}; // 读任务 Callable<Object> readTask = new Callable<Object>() { @Override public Object call() throws Exception { // rLock.lock(); rl.lock(); try { Thread.sleep(1000); s.getValue(); }finally { // rLock.unlock(); rl.unlock(); } return null; }}; // 开始时间 long start = System.currentTimeMillis(); for(int i=0;i<2;i++) { // 写任务执行 2 次 es.submit(writeTask); } for(int i=0;i<18;i++) { // 读任务执行 18 次 es.submit(readTask); } es.shutdown(); // 停止线程池,不在接受新的任务,将现有任务全部执行完毕 while(true) { if(es.isTerminated()) { // 当线程池中所有任务执行完毕,返回true,否则返回false break; } } // 执行到这里,说明线程池中所有任务都执行完毕,可以计算结束时间 System.out.println(System.currentTimeMillis()-start); } } class Student { private int value; //读 public int getValue() { return value; } //写 public void setValue(int value) { this.value = value; } }
static <T> Collection<T> synchronizedCollection(Collection<T> c) //返回由指定集合支持的同步(线程安全)集合。 static <T> List<T> synchronizedList(List<T> list) //返回由指定列表支持的同步(线程安全)列表。 static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) //返回由指定地图支持的同步(线程安全)映射。 static <K,V> NavigableMap<K,V> synchronizedNavigableMap(NavigableMap<K,V> m) //返回由指定的可导航地图支持的同步(线程安全)可导航地图。 static <T> NavigableSet<T> synchronizedNavigableSet(NavigableSet<T> s) //返回由指定的可导航集支持的同步(线程安全)可导航集。 static <T> Set<T> synchronizedSet(Set<T> s) //返回由指定集合支持的同步(线程安全)集。 static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m) //返回由指定的排序映射支持的同步(线程安全)排序映射。 static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s) //返回由指定的排序集支持的同步(线程安全)排序集。