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