java——线程(二)

上一篇线程主要是线程的基本使用方法,这一篇文章讲解线程之间的同步和通信。

线程的同步和通信是一个重点。

很多书上讲解线程之间的同步时,都使用了一个售票系统。

 首先我们用上一篇写知识点,模拟一个售票系统。

public class ThreadDemo2 implements Runnable{

		private int i=100;
		@Override
		public void run() {
			
			while(i>0){
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println("售出第"+(i--)+"张票"+"-----"+Thread.currentThread().getName());
			}
		}

		public static void main(String[] args) {
			ThreadDemo2 runableDemo=new ThreadDemo2();
			Thread th=new Thread(runableDemo,"窗口一");
			Thread th1=new Thread(runableDemo,"窗口二");
			System.out.println("开始买票了");
			th.start();
			th1.start();
		}

   看一下效果图:

       

        会发现,窗口一和窗口二都买出了第98张票。这样是不行啊,所以只能使用同步了。

   接下来介绍一个关键字,synchronized关键字,实现同步代码块

public class ThreadDemo2 implements Runnable{

		private int i=100;
		@Override
		public void run() {
			
			synchronized (this) {//同步代码块
				while(i>0){
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println("售出第"+(i--)+"张票"+"-----"+Thread.currentThread().getName());
				}
			}
		}

		public static void main(String[] args) {
			ThreadDemo2 runableDemo=new ThreadDemo2();
			Thread th=new Thread(runableDemo,"窗口一");
			Thread th1=new Thread(runableDemo,"窗口二");
			System.out.println("开始买票了");
			th.start();
			th1.start();
		}
}
效果图:

我们会发现,售出的票没有了重复。


加一个题外话,今天我去亚信面试,就是一个校招,做了一份题,里面有个线程题,结果是什么?

new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				
				System.out.println("haha");
			}
		}).run();
 我当时没仔细看,说,没有start(),所以没有任何结果。还是年轻,全部都是套路,他并没有调用start()方法,但是调用了run()方法,这个代码的意思就是说,一个Thread的子类对象,调用run()方法,输出的是字符串"haha",这样run()方法就相当于是一个普通的方法,并没有涉及到线程,因为这个线程并没有开启。


    

     synchronized关键字还可以用在方法上

public class ThreadDemo2 implements Runnable{

		private int i=100;
		@Override
		public void run() {
		     this.haha();
		}
		
		public synchronized void haha(){
			while(i>0){
				try {
					Thread.sleep(50);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println("售出第"+(i--)+"张票"+"-----"+Thread.currentThread().getName());
			}
		}

		public static void main(String[] args) {
			ThreadDemo2 runableDemo=new ThreadDemo2();
			Thread th=new Thread(runableDemo,"窗口一");
			Thread th1=new Thread(runableDemo,"窗口二");
			System.out.println("开始买票了");
			th.start();
			th1.start();
		}
}

和上面是有synchronized实现同步代码块的效果一样。

大家会发现,使用synchronized实现的方法或者是同步代码块,只要一个线程占用其同步锁,其他线程是无法获得运行权的。这就是我们的效果,每次只有一个线程进行买票操作。

同步锁:

     lock(),实现加锁操作,unlock()释放同步锁。

public class ThreadDemo2 implements Runnable{
	    private ReentrantLock lock=new ReentrantLock();

		private int i=100;
		@Override
		public void run() {
			
			while(i>1){
				lock.lock();
				try {
					Thread.sleep(50);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println("售出第"+(i--)+"张票"+"-----"+Thread.currentThread().getName());
				lock.unlock();
			}
			
		}
		
		

		public static void main(String[] args) {
			ThreadDemo2 runableDemo=new ThreadDemo2();
			Thread th=new Thread(runableDemo,"窗口一");
			Thread th1=new Thread(runableDemo,"窗口二");
			System.out.println("开始买票了");
			th.start();
			th1.start();
		}
}

效果图:既有线程一,又有线程二


——线程之间通信,简单介绍

 线程之间的通信的方法,全部定义在Object类里面

public class Object {

    private static native void registerNatives();
    static {
        registerNatives();
    }

    public final native Class<?> getClass();

    public native int hashCode();

    public boolean equals(Object obj) {
        return (this == obj);
    }

    protected native Object clone() throws CloneNotSupportedException;

    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }


    public final native void notify();

    public final native void notifyAll();

    public final native void wait(long timeout) throws InterruptedException;

    public final void wait(long timeout, int nanos) throws InterruptedException {
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos > 0) {
            timeout++;
        }

        wait(timeout);
    }

    public final void wait() throws InterruptedException {
        wait(0);
    }

    protected void finalize() throws Throwable { }
}

通信常用的就是wait(),notify(),notifyAll()。

这是多线程的基础,下一篇应该会深入了解一下多线程。









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值