java线程相关的包是java.util.concurrent,也就是大名鼎鼎的juc,线程同步的相关类与接口都在这个包里。java关于线程同步的问题设计了一个关键字,叫做synchronized,利用这个关键字可以避免多线程情况下的脏数据问题,使用方法很简单,就是在后面的参数里填上同步监视器(俗称“锁”),当锁没有被任何线程占用时,任何线程都可以将锁握住。当锁被握住时,其他进程无法拥有锁,进而无法进入synchronized关键字规定的同步区域中,无锁的进程被阻塞,等待锁被释放出来再次去争夺锁。(说白了就是锁内区域代码都是单线程,无法并发执行)
为了编码更复杂的代码,java引入了等待与超时等待两个状态,当拥有锁的进程通过锁去调用wait()方法时,就会进入等待或超时等待的状态,此时该线程锁拥有的锁将被释放,重新被剩余的线程锁争夺,该线程该如何回到runnable呢?需要该锁去调用notify()才可。当然,除了wait和notify外,还有许多进入和出去wait状态的方法。
api介绍
操作线程有两个地方,一个是父类object中定义的wait()等方法,另一个是Thread类中定义的相关方法。
Thread类中定义的关于线程的api
start()
:重启当前线程;调用当前线程的run()run()
:通常需要重写Thread类中的方法,将创建的线程要执行的操作声明再此方法中
这个方法开发者很少调用,因为这是线程的方法的容器,直接调用只是普通的调用方法而已,不能开启新线程,开启新线程需要调用start()这个方法。getName()
:获取当前线程的名字setName()
:设置当前线程的名字currentThread()
:静态方法,返回当前代码执行的线程,是一个Thread类型
下面的方法理解起来比较复杂
yield()
:静态方法,让 当前线程 让出cpu运算执行权,调用此方法后,会将当前线程挂起,也就是从运行中转到就绪态,后面的指令仍旧会执行,只不过暂停在此处了,等cpu分配到这个线程,继续从此处开始,但是!不一定可以成功,是否成功需要看条件,我试了一下,没成功。这方法没什么用(开发者而言)
-
join()
:要求调入其他线程的方法,该线程让步
使用线程的对象进行调用,例如一个线程类对象Thread t1,t1.join(),这样用,那么这行代码下面的代码必须等t1这个线程执行完才可以继续执行,下面是一个小例子public class Test1 implements Runnable { @Override public void run() { try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(currentThread()+"over"); } public static void main(String[] args) throws InterruptedException, ExecutionException { Test1 test1 = new Test1(); Thread t1 = new Thread(test1); Thread t2 = new Thread(test1); t1.start(); t2.start(); //如果没有调用join方法,那么System.out.println(currentThread());必定是在两个线程前执行 t1.join(); t2.join(); System.out.println(currentThread()); } }
-
stop()
:已过时,强制结束当前线程 -
sleep(long millitime)
:让当前线程“睡眠”制定的毫秒,停设置的毫秒数 -
isAlive()
:判断是否存活 -
优先级:
MAX_PRIORITY :10
MIN PRIORITY :1
NORM_PRIORITY :5 默认是5
设置方法:getPriority ():返回线程优先值 setPriority (int newPriority ): 改变线程的优先级
Object类下面的方法
wait() / notify() / notifyAll()
线程状态转换:就线程自己的控制,不直接涉及别的线程
wait方法可以控制当前的线程,因为调用wait方法会使得当前线程阻塞,释放同步锁,不过是否会对其他线程产生影响是取决于程序设计。如果别的线程需要这把锁,那么这两个线程就关联起来了,这从整体上来看就是线程A阻塞,释放锁,线程B握锁进入同步方法。
wait()会释放锁,用notify()会恢复(使用流程见ppt画板)
释义:wait():一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器
notify():执行此方法,唤醒被wait的一个线程。如果有多个线程被wait,就唤醒优先级高的。(notify后的线程直接退出当前同步方法体。)
notifyAll():唤醒所有的线程。
注意:
- 以上3个方法的使用前提:必须使用在同步代码块或同步方法中(synchronize)
- 调用要求:三个方法的调用者,必须是同步监视器(对象),否则会出现IllegalMonitorStateException。
- 因为要保证任何一个方法都有notify(),notifyAll(),这三个方法是定义在Java.lang.Object类中的。