您的位置:首页 > 编程语言 > Java开发

Java-多线程总结

2015-01-19 16:27 281 查看
1.调用run和调用start有什么区别

run方法只是类里的一个普通方法,调用该方法只是执行该方法里的代码,程序中还是只有主线程这一线程

而start方法是将该线程变成可运行状态(还没运行),等待cpu切换来时就可以启动执行该线程下的run方法。

即start方法可以启动线程,而run方法只是Thread的一个普通方法。

2.静态的同步方法与其他同步代码块之间的同步

静态同步方法:public static synchronized void method(){...};

//它的同步锁是该方法所属字节码文件对象即 类名.getClass()或 类名.class

所以与它同步的代码块里必须是:synchronized(类名.class) {.....}

非静态的方法的同步锁是this对象本身

3.总结

同步的好处:解决了线程的安全问题。

同步的弊端:相对降低了效率,因为同步外的线程的都会判断同步锁。

同步的前提:同步中必须有多个线程并使用同一个锁。

4.wait 和 sleep 区别?

wait可以指定时间也可以不指定。sleep必须指定时间。

在同步中时,对cpu的执行权和锁的处理不同。 wait:释放执行权,释放锁。 sleep:释放执行权,不释放锁。

5.wait,notify,notifyAll方法使用

这三个方法经常用在线程间的通信,比如:X线程对某个数据进行一次更改后,Y线程对其读取一次,是一次更改一次读取交替进行,

不是更改多次后再读取多次。它们只能在同步方法或同步代码块中调用,且同步锁必须为这三个方法的共同对象。无论线程调用一个

对象的wait还是notify方法,该线程必须先得到该对象的锁,才可以调用该方法。notify只能唤醒同一个对象监视器中调用wait的线程。

以下是,生产者生产(更改)一次后,换消费者消费(读取)一次。依次交替。

package hq.Thread.Test;

public class Test {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Q q=new Q ();
Consumer c=new Consumer(q);
Producer p=new Producer (q);
new Thread (c).start();
new Thread (p).start();

}

}
//消费者线程(读取)
class Consumer implements Runnable
{
private Q q=null;
public Consumer (Q q)
{
this.q=q;
}
public void run ()
{
while(true)
{
//System.out.println(Thread.currentThread().getName());
try {
q.get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

}
//生产者线程(更改)
class Producer implements Runnable
{
private Q q=null;
private int num=1;
public Producer (Q q)
{
this.q=q;
}
public void run ()
{
while(true)
{

//System.out.println(Thread.currentThread().getName());
if(num==1)
{
try {
q.put("陈奕迅","男");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else if(num==0)
{
try {
q.put("王菲","女");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

num=(num+1)%2;
}
}
}
//共同操作的数据Q,由线程对其进行修改,读取,
//因为要修改和读取同步(即两个方法的同步锁为Q对象),且数据在Q内部,所以应具有操作数据的方法
class Q
{
private String name;
private String sex;
private boolean flag=true;//以标志位来控制更改或读取操作。
//更改的同步方法
public synchronized void put(String name,String sex) throws InterruptedException
{
//默认标志位为true时更改否则等待
if(!isFlag())
wait();
this.name=name;
this.sex=sex;
//更改完后换读取,且唤醒读取(为false标志)的线程
this.flag=false;
notify();
System.out.println(Thread.currentThread().getName());

}
//读取的同步方法
public synchronized void get() throws InterruptedException
{
//默认标志位为flase时读取否则等待
if(isFlag())
wait();
System.out.println(this.name+":"+this.sex);
//读取完后换更改,且唤醒更改(为true)的线程
this.flag=true;
notify();
System.out.println(Thread.currentThread().getName());

}

public boolean isFlag()
{
return flag;
}
public void setFlag(boolean flag)
{
this.flag=flag;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name=name;
}
public String getSex()
{
return sex;
}
public void getSex(String sex)
{
this.sex=sex;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: