如果一个线程执行了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 {
public static void main(String[] args)
{
CallableThreadTest ctt = new CallableThreadTest();
FutureTask 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的同步锁之后才能运行。
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修饰方法,这是一种粗粒度锁;这个同步方法(非static方法)无需显式指定同步监视器,同步方法的同步监视器是this,也就是调用该方法的对象。synchronized代码块
是用synchronized修饰代码块,这是一种细粒度锁。线程开始执行同步代码块之前,必须先获得对同步监视器的锁定,任何时候只能有一个线程可以获得对同步监视器的锁定,当同步代码块执行完成后,该线程会释放对同步监视器的锁定。虽然Java允许使用任何对象作为同步监视器,但同步监视器的目的就是为了阻止两个线程对同一个共享资源进行并发访问,因此通常推荐使用可能被并发访问的共享资源充当同步监视器。
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 writeTask = new Callable() {
@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 readTask = new Callable() {
@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 Collection synchronizedCollection(Collection c)
//返回由指定集合支持的同步(线程安全)集合。
static List synchronizedList(List list)
//返回由指定列表支持的同步(线程安全)列表。
static Map synchronizedMap(Map m)
//返回由指定地图支持的同步(线程安全)映射。
static NavigableMap synchronizedNavigableMap(NavigableMap m)
//返回由指定的可导航地图支持的同步(线程安全)可导航地图。
static NavigableSet synchronizedNavigableSet(NavigableSet s)
//返回由指定的可导航集支持的同步(线程安全)可导航集。
static Set synchronizedSet(Set s)
//返回由指定集合支持的同步(线程安全)集。
static SortedMap synchronizedSortedMap(SortedMap m)
//返回由指定的排序映射支持的同步(线程安全)排序映射。
static SortedSet synchronizedSortedSet(SortedSet s)
//返回由指定的排序集支持的同步(线程安全)排序集。,v>,v>,v>,v>,v>,v>,v>,v>,v>
全部0条评论
快来发表一下你的评论吧 !