多线程一 几个方法区别

sleep() 和 wait() 有什么区别? 搞线程的最爱
  sleep()方法是使线程停止一段时间的方法。在sleep 时间间隔期满后,线程不一定立即恢复执行。这是因为在那个时刻,其它线程可能正在运行而且没有被调度为放弃执行,除非(a)“醒来”的线程具有更高的优先级 (b)正在运行的线程因为其它原因而阻塞。
wait()是线程交互时,如果线程对一个同步对象(方法)x 发出一个wait()调用,该线程会暂停执行,被调对象(方法)进入等待状态,直到被唤醒或等待时间到。

Wait时别的线程[b]可以[/b]访问锁定对象([color=red]调用wait,锁就撒手[/color]);
调用wait方法的时候必需锁定该对象;
Object提供的方法
Sleep时别的线程也[b]不可以[/b]访问锁定对象([color=red]睡着也抱着锁[/color]);
Thread提供的方法
请参考下面2个例子就全明白了......
[size=large]

[color=red]同步:
a.每个对象只有一把锁
b.一个线程访问同步方法时候,别的线程可以访问该对象的其他非同步的方法,而且也可以影响同步方法内部的变量。[/color][/size]

例1:

public class TT implements Runnable {
int b = 100;

public synchronized void m1() throws Exception{
b = 1000;
Thread.sleep(1000);
System.out.println("b = " + b);
}

public synchronized void m2() throws Exception {
Thread.sleep(3000);
b = 2000;
}

public void run() {
try {
m1();
} catch(Exception e) {
e.printStackTrace();
}
}

public static void main(String[] args) throws Exception {
TT tt = new TT();
Thread t = new Thread(tt);
t.start();
tt.m2();

System.out.println(tt.b);
}
}


===输出结果有2中可能====
如果主线程锁定当前对象,输出结果为:
2000
b = 1000
如果子线程锁定当前对象,输出结果为:
1000
b = 1000



[color=red][b]例2:范例名称:生产者--消费者问题
遇到互斥的问题时候如何解决得呢?
答:将互斥的2个操作放到同一个类的2个方法中,然后让这2个方法都加上synchronized关键字修饰
[/b][/color]

/* * 源文件名称:SyncTest.java
* 要 点:
* 1. 共享数据的不一致性/临界资源的保护
* 2. Java对象锁的概念
* 3. synchronized关键字/wait()及notify()方法
*/



package com.wlh;

public class ProduceConsumer {
public static void main(String args[]){
SyncStack stack = new SyncStack();
Runnable p=new Producer(stack);
Runnable c = new Consumer(stack);
Thread t1 = new Thread(p);
Thread t2 = new Thread(c);
t1.start();
t2.start();
}
}

/**
* 支持多线程同步操作的堆栈的实现
* 因为只有一个线程能够锁定当前对象,而同步方法的执行前先锁定当前对象,
* 所以同一时刻,同步方法push和pop只能有一个在执行
* @author wulihai
*/
class SyncStack{
private int index = 0;
private char []data = new char[6];

public synchronized void push(char c){
if(index == data.length){
try{
this.wait();
}catch(InterruptedException e){}
}
this.notify();
data[index] = c;
index++;
}
public synchronized char pop(){
if(index ==0){
try{
this.wait();
}catch(InterruptedException e){}
}
this.notify();
index--;
return data[index];
}
}


class Producer implements Runnable{
SyncStack stack;
public Producer(SyncStack s){
stack = s;
}
public void run(){
for(int i=0; i<20; i++){
char c =(char)(Math.random()*26+'A');//
stack.push(c);
System.out.println("produced:"+c);
try{
Thread.sleep((int)(Math.random()*1000)); //随机休息,这样看起来生产和消费的产品个数都是随机的
}catch(InterruptedException e){
}
}
}
}


class Consumer implements Runnable{
SyncStack stack;
public Consumer(SyncStack s){
stack = s;
}
public void run(){
for(int i=0;i<20;i++){
char c = stack.pop();
System.out.println("消费:"+c);
try{
Thread.sleep((int)(Math.random()*1000));//随机休息,这样看起来生产和消费的产品个数都是随机的
}catch(InterruptedException e){
}
}
}
}




[size=large]
[color=red]死锁:当一个或多个进程等待系统资源,而系统资源又同时被此进程本身或者其它进程占用[/color][/size]

例:结果2个线程谁都不打印输出数据

package com.wlh;

public class DeadLock extends Thread {


int flag=0;
static Object o1=new Object();
static Object o2=new Object();

public DeadLock(int flag){
this.flag=flag;
}
@Override
public void run() {
if(this.flag==1){
synchronized(o1){
System.out.println(Thread.currentThread().getName()+"锁定对象o1");
try {
Thread.sleep(1000);//让另一个线程能进入另一块区域,锁定对象o2
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(o2){
System.out.print("this.flag="+this.flag);
}
}

}
if(this.flag==2){
synchronized(o2){
System.out.println(Thread.currentThread().getName()+"锁定对象o2");
try {
Thread.sleep(1000);//让另一个线程能进入另一块区域,锁定对象o1
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(o1){
System.out.print("this.flag="+this.flag);
}

}
}
}

public static void main(String []args){
DeadLock d1=new DeadLock(1);
DeadLock d2=new DeadLock(2);
d1.start();
d2.start();
}
}




[size=large][color=red]Join方法:将某个子线程合并到主线程,即等子线程全部运行全部执行完之后才执行主线程[/color][/size]
例1:

package com.wlh;

public class TestJoin {
public static void main(String[] args) {
MyThread2 t1 = new MyThread2("子线程");
t1.start();
/* try {
t1.join();
} catch (InterruptedException e) {}*/

for(int i=1;i<=10;i++){
try {
Thread.sleep(1000);//当前线程休息1000秒
System.out.println("i am main thread");
} catch (InterruptedException e) {
e.printStackTrace();
}

}
}
}
class MyThread2 extends Thread {
MyThread2(String s){
super(s);
}

public void run(){
for(int i =1;i<=10;i++){
System.out.println("i am "+getName());
try {
sleep(1000);//当前线程休息1000秒
} catch (InterruptedException e) {
return;
}
}
}
}




备注:子线程和主线程交替执行
i am 子线程
i am main thread
i am 子线程
i am main thread
i am 子线程
i am main thread
i am 子线程
i am main thread
i am 子线程
i am main thread
i am 子线程
i am main thread
i am 子线程
i am main thread
i am 子线程
i am main thread
i am 子线程
i am main thread
i am 子线程
i am main thread


[size=large]例2:在 t1.start()子线程就绪;之后添加t1.join(),则等t1线程执行完之后才执行主线程[/size]


package com.wlh;

public class TestJoin {
public static void main(String[] args) {
MyThread2 t1 = new MyThread2("子线程");
t1.start();
try {
t1.join();
} catch (InterruptedException e) {}
for(int i=1;i<=10;i++){
try {
Thread.sleep(1000);//当前线程休息1000秒
System.out.println("i am main thread");
} catch (InterruptedException e) {
e.printStackTrace();
}

}
}
}
class MyThread2 extends Thread {
MyThread2(String s){
super(s);
}

public void run(){
for(int i =1;i<=10;i++){
System.out.println("i am "+getName());
try {
sleep(1000);//当前线程休息1000秒
} catch (InterruptedException e) {
return;
}
}
}
}


输出结果:

i am 子线程
i am 子线程
i am 子线程
i am 子线程
i am 子线程
i am 子线程
i am 子线程
i am 子线程
i am 子线程
i am 子线程
i am main thread
i am main thread
i am main thread
i am main thread
i am main thread
i am main thread
i am main thread
i am main thread
i am main thread
i am main thread


[color=red][size=large]Yeild方法:当前线程让出CPU的时间给其他线程执行一会。注意:是让出一会儿,待会又回来了。。。[/size][/color]




package com.wlh;
public class TestYield {
public static void main(String[] args) {
MyThread3 t1 = new MyThread3("t1");
MyThread3 t2 = new MyThread3("t2");
t1.start(); t2.start();
}
}
class MyThread3 extends Thread {
MyThread3(String s){super(s);}
public void run(){
for(int i =1;i<=100;i++){
System.out.println(getName()+": "+i);
if(i%10==0){
yield();
}
}
}
}

[color=red]输出结果:只要一个线程执行到10的整数倍,必然让出CPU的时间给其他线程执行一会[/color]
t1: 1
t1: 2
t1: 3
t1: 4
t1: 5
t1: 6
t1: 7
t1: 8
t1: 9
t1: 10
t2: 1
t2: 2
t2: 3
t2: 4
t2: 5
t2: 6
t2: 7
t2: 8
t2: 9
t2: 10
t1: 11
t1: 12
t1: 13
t1: 14
t1: 15
t1: 16
t1: 17
t1: 18
t1: 19
t1: 20
t2: 11
t2: 12
t2: 13
t2: 14
t2: 15
...........
..............
...................
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值