`
wlh269
  • 浏览: 455790 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

多线程一 几个方法区别

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

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


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


例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



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


/* * 源文件名称: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){   
            }   
        }   
    }   
}  





死锁:当一个或多个进程等待系统资源,而系统资源又同时被此进程本身或者其它进程占用


例:结果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();
	}
}






Join方法:将某个子线程合并到主线程,即等子线程全部运行全部执行完之后才执行主线程
例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


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

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



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



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();
      }
    }
  }
}

输出结果:只要一个线程执行到10的整数倍,必然让出CPU的时间给其他线程执行一会
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
...........
..............
...................
分享到:
评论

相关推荐

    3种多线程实现同步方法

    然而,多线程也带来了数据同步的问题,因为多个线程可能同时访问共享资源,如果不加以控制,就可能导致数据不一致或引发错误。本篇文章将深入探讨三种在C++中实现多线程同步的方法:事件对象、关键代码段和互斥对象...

    初始化多线程的几种方法

    在处理多线程时,有几个关键概念和特性需要理解: - **线程同步**:为了避免线程间的冲突,需要同步对共享资源的访问。C#提供了`Mutex`, `Semaphore`, `Monitor`, `lock`等机制。 - **线程优先级**:每个线程都有...

    易语言多线程多次启动一个子程序

    易语言,作为一款中国本土的、面向初学者和专业开发者都友好的编程工具,同样支持多线程编程。本节将详细讨论如何在易语言中实现多线程以及多次启动同一个子程序。 一、易语言简介 易语言是一种以中文作为编程语句...

    线程的几个重要方法.doc

    本文将详细讲解Java中线程的几个关键方法及其应用场景。 1. `run()`方法 `run()`方法是线程执行的主要逻辑所在。当创建一个线程并调用`start()`方法时,Java虚拟机(JVM)会自动调用`run()`方法。`run()`方法必须是`...

    多线程编程示例

    多线程编程涉及到几个关键概念: 1. **线程同步**:当多个线程访问同一资源时,可能导致数据不一致。为此,可以使用锁(Mutex, Semaphore, Monitor等)或者`lock`关键字来确保同一时间只有一个线程访问共享资源。 2....

    关于多线程的一个小程序

    在多线程编程中,有以下几个关键概念: 1. 线程安全:当多个线程访问同一数据时,如果代码能保证数据的完整性和一致性,那么我们就说这个代码是线程安全的。为了实现线程安全,通常需要使用锁(如互斥量、信号量)或...

    多线程_按键精灵经典多线程操作_

    多线程在按键精灵中的应用主要体现在以下几个方面: 1. **并行执行任务**:通过开启多个线程,按键精灵能够同时处理不同的任务,例如在一个线程中打开应用程序,另一个线程执行特定的点击或输入操作,这使得自动化...

    vbs的多线程的解决方法

    本文将详细介绍几种在VBS中模拟多线程的方法,并探讨它们的应用场景和技术细节。 #### 1. 使用WScript.Shell.Run模拟并发执行 VBS可以通过`WScript.Shell.Run`方法来启动其他进程或脚本,从而达到模拟多线程的效果...

    易语言多线程访问网页

    在多线程访问网页的场景中,通常涉及到以下几个关键知识点: 1. **线程基础**:线程是操作系统调度的基本单位,一个进程可以包含多个线程。在易语言中,通过创建和管理线程,可以并发地执行多个任务。创建线程的...

    c#多线程socket开发(一个服务器对多个客户端)

    在服务器端的多线程实现中,我们使用while循环不断地监听客户端的连接请求,并在accept方法中创建一个新的ClientThread对象,以便处理客户端的连接请求。 多线程Socket服务器端程序的优点 使用C#语言开发多线程...

    易语言多线程传递自定义数据(免加延时方法)

    总结来说,易语言的多线程编程涉及以下几个关键知识点: 1. **创建和结束线程**:使用易语言提供的指令创建和结束线程。 2. **参数传递**:通过函数参数将数据传递给线程,可以是基本类型、结构体或引用类型。 3. *...

    e语言几个简单多线程写法

    标题"e语言几个简单多线程写法"表明本文将探讨如何在e语言(可能指的是Erlang或者一种类似的编程语言)中实现多线程编程,适用于初学者。描述中提到“新手可以参考源码多学习一下,我也是在学习中”,暗示我们将分享...

    C#的多线程示例;几个多线程之间的互斥,同步;WPF主界面INVOKE

    多线程是指一个应用程序内同时运行多个独立的执行线程。在C#中,可以使用`System.Threading`命名空间中的`Thread`类创建和管理线程。通过开启新线程,我们可以让CPU在处理一项任务的同时进行其他任务,提高程序的...

    JAVA单线程多线程

    单线程的优势主要体现在以下几个方面: 1. **简化程序设计**:由于无需处理多线程间的竞争条件或死锁等问题,因此程序设计更加简单明了。 2. **易于调试**:单线程程序的调试相对容易,因为不存在多个线程之间复杂的...

    深入浅出 Java 多线程.pdf

    多线程编程有以下几个优点: 1. 提高程序的执行效率:多线程编程可以同时执行多个任务,从而提高程序的执行效率。 2. 提高程序的响应速度:多线程编程可以提高程序的响应速度,因为它可以同时执行多个任务。 3. ...

    C++多线程 最简易的多线程程序

    一个简单的多线程程序通常包括以下几个步骤: 1. **创建线程**:创建新线程时,我们需要传递一个可调用对象(如函数或函数对象)以及其可能的参数。例如,我们可以定义一个函数`void threadFunction(int arg)`,...

    一个多线程下载程序

    标题 "一个多线程下载程序" 描述了一个使用VC++编程语言实现的软件,该软件能够通过多线程技术加速文件的下载过程。多线程下载是现代互联网应用程序中常见的优化技术,尤其对于大文件下载,它能显著提高下载速度,...

    多线程的运用e语言多线程 e多线程

    在E语言中,创建一个新的线程通常涉及到以下几个步骤: 1. 引入线程库:首先,你需要确保E语言支持多线程,并正确引入相关的库或模块。 2. 定义线程函数:创建一个函数,该函数将作为新线程的执行体。 3. 创建线程:...

    Java多线程知识点总结

    Java多线程是Java编程语言中一个非常重要的概念,它允许开发者在一个程序中创建多个执行线程并行运行,以提高程序的执行效率和响应速度。在Java中,线程的生命周期包含五个基本状态,分别是新建状态(New)、就绪...

    Linux下基于多线程的服务器程序设计.pdf

    为了解决这些问题,文章介绍了一种基于Linux下的多线程服务器程序设计方法。 多线程服务器程序设计的优点是可以解决传统服务器工作方式的三个缺点。首先,创建线程比创建进程快10~100倍,能快速地响应客户请求。...

Global site tag (gtag.js) - Google Analytics