1.sleep
是Thread的静态方法,public static void sleep(long mililis) throws InterruptedException 使得当前线程处于休眠状态。Tread.sleep();
sleep() 允许指定以毫秒为单位的一段时间作为参数,它使得线程在指定的时间内进入阻塞状态,不能得到CPU 时间片,指定的时间一过,线程重新进入可执行状态。说白了 ,也就是把机会给其他线程,但是监控状态依然保持。重要的一点就是 当调用sleep()方法是 不会 释放对象锁的。
举例:
public class SleepTest implements Runnable {
static int b = 100;
public void run() {
try {
System.out.println("m1");
b--;
Thread.sleep(5000);
System.out.println("m1" + "Thread=" + Thread.currentThread().getName()
+ " " + this + " " + "b=:" + b);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) throws Exception {
SleepTest ss = new SleepTest();
Thread tt = new Thread(ss);
Thread tt1 = new Thread(ss);
tt.start();
tt1.start();
}
}
运行结果:
m1
m1
m1Thread=Thread-0 CopyOfsynchro@f62373 b=:98
m1Thread=Thread-1 CopyOfsynchro@f62373 b=:98
2.wait,notify,notifyall
是Object 类的方法。所有对象都拥有这一对方法。这一对方法阻塞时要释放占用的锁,而锁是任何对象都具有的,调用任意对象的 wait() 方法导致线程阻塞,并且该对象上的锁被释放。
notify()是释放对象的wait()方法而阻塞线程(但是也要当得到锁后才可以运行)但是这个释放是随机的,也就是不一定要释放那个线程。(因为调用同一资源的可能不是一个线程或者说是有多个阻塞的线程在等待,但是如果加了synchronized也只有一个线程,也有其他的线程在等待中,也就是阻塞)我们无法预料哪一个线程将会被选择,所以编程时要特别小心,避免因这种不确定性而产生问题。
除了 notify(),还有一个方法 notifyAll() 也可起到类似作用,唯一的区别在于,调用 notifyAll() 方法将把因调用该对象的 wait() 方法而阻塞的所有线程一次性全部解除阻塞。当然,只有获得锁的那一个线程才能进入可执行状态。但是这一对方法却必须在 synchronized 方法或块中调用,理由也很简单,只有在synchronized 方法或块中当前线程才占有锁,才有锁可以释放。
同样的道理,调用这一对方法的对象上的锁必须为当前线程所拥有,这样才有锁可以释放。因此,这一对方法调用必须放置在这样的 synchronized 方法或块中,该方法或块的上锁对象就是调用这一对方法的对象。若不满足这一条件,则程序虽然仍能编译,但在运行时会出现 IllegalMonitorStateException 异常。
举例:生产者与消费者
public class ProducerConsumer {
public static void main(String args[]){
SyncStack ss = new SyncStack();
Producer p = new Producer(ss);
Consumer c = new Consumer(ss);
new Thread(p).start();
new Thread(c).start();
}
}
class WoTou{
int id ;
public WoTou(int id){
this.id = id;
}
public String toString(){
return "WoTou:"+id;
}
}
class SyncStack{
int index = 0;
WoTou[] awtWT = new WoTou[6];
public synchronized void push(WoTou wt){
while(index == awtWT.length){
try {
this.wait();//当前的正在访问对象的线程wait
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();
awtWT[index] = wt;
index ++;
}
public synchronized WoTou pop(){
while(index == 0){//if->while:如果catch住异常后,假如是if并且index=0,index == 0 不再判断,index--会执行, 程序错误。所以改为while,可以避免发生如此错误。
try {
this.wait();//当前的正在访问对象的线程阻塞(wait),wait后对象的锁不归线程所有,直到"醒了"(notify,notifyALL),再重新找回锁。
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();//叫醒一个正在当前对象上wait的线程。
index--;
return awtWT[index];
}
}
class Producer implements Runnable{
SyncStack ss = null;
Producer(SyncStack ss){
this.ss = ss;
}
public void run() {
for(int i=0;i<20;i++){
WoTou wt = new WoTou(i);
ss.push(wt);
System.out.println("Producer:"+wt);
try {
Thread.sleep((int)(Math.random()*100));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable{
SyncStack ss = null;
Consumer(SyncStack ss){
this.ss = ss;
}
public void run() {
for(int i=0;i<20;i++){
WoTou wt = ss.pop();
System.out.println("Consumer:"+wt);
try {
Thread.sleep((int)(Math.random()*1000));//目的是让其他线程有执行的机会。
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
执行结果:
Producer:WoTou:0
Consumer:WoTou:0
Producer:WoTou:1
Producer:WoTou:2
Producer:WoTou:3
Producer:WoTou:4
Producer:WoTou:5
Producer:WoTou:6
Consumer:WoTou:6
Producer:WoTou:7
Producer:WoTou:8
Consumer:WoTou:7
Producer:WoTou:9
Consumer:WoTou:8
Consumer:WoTou:9
Producer:WoTou:10
Consumer:WoTou:10
Producer:WoTou:11
Consumer:WoTou:11
Producer:WoTou:12
Consumer:WoTou:12
Producer:WoTou:13
Consumer:WoTou:13
Producer:WoTou:14
Consumer:WoTou:14
Producer:WoTou:15
Consumer:WoTou:15
Producer:WoTou:16
Consumer:WoTou:16
Producer:WoTou:17
Consumer:WoTou:17
Producer:WoTou:18
Consumer:WoTou:18
Producer:WoTou:19
Consumer:WoTou:19
Consumer:WoTou:5
Consumer:WoTou:4
Consumer:WoTou:3
Consumer:WoTou:2
Consumer:WoTou:1
3.join
合并某个线程。(相当方法调用)
举例:
public class TestJoin implements Runnable {
static int b = 100;
public void run() {
try {
System.out.println("m1");
b--;
System.out.println("m1" + "Thread=" + Thread.currentThread().getName()
+ " " + this + " " + "b=:" + b);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) throws Exception {
TestJoin ss = new TestJoin();
Thread tt = new Thread(ss);
Thread tt1 = new Thread(ss);
tt.start();
tt.join(); //合并线程
tt1.start();
}
}
运行结果:
m1
m1Thread=Thread-0 TestJoin@12b6651 b=:99
m1
m1Thread=Thread-1 TestJoin@12b6651 b=:98
4.yield
让出CPU给其他线程执行的机会。
举例:
public class TestYield extends Thread {
public void run() {
try {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() +"i=:" + i);
if(i%10==0){
yield(); //让出线程执行
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) throws Exception {
Thread tt = new TestYield();
Thread tt1 = new TestYield();
tt.start();
tt1.start();
}
}
5.getPriority,setPriority
Java 提供一个线程调度器来监控程序中启动后就进入就绪状态的所有线程。线程调度器按照线程的优先级决定应调度哪个线程来执行。
线程的优先级用数字表示,范围从1到10,一个线程的缺省优先级是5。
Thread.MIN_PRIORITY = 1
Thread.MAX_PRIORITY=10
Thread.NORM_PRIORITY = 5
使用下述方法获得或设置线程对象的优先级。
int getPriority();
void setPriority(int nexPriority);
举例:
public class TestPriority extends Thread{
public void run() {
try {
for(int i=0;i<10;i++){
System.out.println("m1" + "Thread="
+ Thread.currentThread().getName() + " " + this + " "
+ "i=:" + i);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) throws Exception {
Thread ss = new TestPriority();
Thread tt = new TestPriority();
ss.start();
tt.start();
tt.setPriority(Thread.NORM_PRIORITY + 4);
}
}
一种运行结果:
m1Thread=Thread-0 Thread[Thread-0,5,main] i=:0
m1Thread=Thread-1 Thread[Thread-1,9,main] i=:0
m1Thread=Thread-1 Thread[Thread-1,9,main] i=:1
m1Thread=Thread-1 Thread[Thread-1,9,main] i=:2
m1Thread=Thread-1 Thread[Thread-1,9,main] i=:3
m1Thread=Thread-1 Thread[Thread-1,9,main] i=:4
m1Thread=Thread-1 Thread[Thread-1,9,main] i=:5
m1Thread=Thread-1 Thread[Thread-1,9,main] i=:6
m1Thread=Thread-1 Thread[Thread-1,9,main] i=:7
m1Thread=Thread-1 Thread[Thread-1,9,main] i=:8
m1Thread=Thread-1 Thread[Thread-1,9,main] i=:9
m1Thread=Thread-0 Thread[Thread-0,5,main] i=:1
m1Thread=Thread-0 Thread[Thread-0,5,main] i=:2
m1Thread=Thread-0 Thread[Thread-0,5,main] i=:3
m1Thread=Thread-0 Thread[Thread-0,5,main] i=:4
m1Thread=Thread-0 Thread[Thread-0,5,main] i=:5
m1Thread=Thread-0 Thread[Thread-0,5,main] i=:6
m1Thread=Thread-0 Thread[Thread-0,5,main] i=:7
m1Thread=Thread-0 Thread[Thread-0,5,main] i=:8
m1Thread=Thread-0 Thread[Thread-0,5,main] i=:9
优先级高的运行时间长。