关于Java Thread线程中 start、stop、wait、join、yield、notify、notifyAll 方法和synchronized的使用

 在下面将会通过几个例子进行分析Thread的各个方法的使用,和实现Thread的方法

1、Thread 通过继承Thread 重写run方法 和 实现Runnable  实现run方法

package com.abc.test1;

/**
 * @author 别说难忘记
 *
 */
public class Tester {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		PrinterThread pt =new PrinterThread();
		Thread t =new Thread(new SayThread());
		t.start();
		pt.start();
	}

}

class PrinterThread extends Thread{
	
	@Override
	public void run() {
		for(int i=0;i<10;i++) {
			System.out.println("打印一条提示!");
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
		}
	}
}

class SayThread implements Runnable{

	@Override
	public void run() {
		for(int i=0;i<10;i++) {
			System.out.println("打印一条欢迎词!");
			try {
				Thread.sleep(800);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}	
	}
}

2、在下面这个例子中,两个线程调用同一个对象,如果没有对addCnt方法用synchronized锁,将会出现数据没有同步而造成的的数据增量丢失。(本例需要自行切换run方法当中count对象的addCnt方法)

并且通过以下两种方法同步:

  1. synchronized块的数据同步
  2. synchronized方法数据同步
package com.abc.test2;

/**
 * @author 别说难忘记
 *
 */
public class Tester {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Count cnt = new Count();
		PrinterThread pt1 =new PrinterThread(cnt);
		PrinterThread pt2 =new PrinterThread(cnt);
		pt1.start();
		pt2.start();	
	}
}
class PrinterThread extends Thread{
	
	private Count cnt;
	
	public PrinterThread(Count cnt){
		this.cnt = cnt;
	}
	
	@Override
	public void run() {
		for(int i=0;i<10;i++) {
			cnt.addCntK();
			try {
				Thread.sleep(300);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}	
	}	
}

class Count{
	
	private int cnt =1;

	public int getCnt() {
		return cnt;
	}

	public void setCnt(int cnt) {
		this.cnt = cnt;
	}
	
	/**
	 * 没有使用synchronized的情况
	 */
	public void addCnt() {
		System.out.println("当前cnt的值为:"+cnt);
		cnt++;
	}
	/**
	 * 使用synchronize方法的写法
	 */
	public synchronized void addCntF() {
		System.out.println("当前cnt的值为:"+cnt );
		cnt++;
	}
	/**
	 * 使用synchronize块的写法
	 */
	public synchronized void addCntK() {
		synchronized (this) {
			System.out.println("当前cnt的值为:"+cnt);
			cnt++;

		}
	}
}

代码执行结果:

1.执行addCnt方法:

2、执行addCntK方法:

3、执行addCntF方法:

3、下面这个例子使用了wait方法使得一个线程进入阻塞状态等待唤醒,另一个线程执行结束在通过notifyAll方法将所有阻塞状态的线程唤醒。

package com.abc.test3;

/**
 * @author 别说难忘记
 *
 */
public class Tester {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Count cnt = new Count();
		PrinterThreadA pt1 = new PrinterThreadA(cnt);
		PrinterThreadB pt2 = new PrinterThreadB(cnt);
		pt1.start();
		pt2.start();
	}
}

class PrinterThreadA extends Thread {

	private Count cnt;

	public PrinterThreadA(Count cnt) {
		this.cnt = cnt;
	}

	@Override
	public void run() {
		cnt.addCntK();
	}
}

class PrinterThreadB extends Thread {

	private Count cnt;

	public PrinterThreadB(Count cnt) {
		this.cnt = cnt;
	}

	@Override
	public void run() {
		cnt.addCntF();
	}
}

class Count {
	private int cnt = 1;

	/**
	 * 使用synchronize块的写法
	 */
	public synchronized void addCntF() {
		for (int i = 0; i < 10; i++) {
			System.out.println("当前cnt的值为:" + cnt + "当前Thread:B");
			cnt++;
			try {
				Thread.sleep(300);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		notifyAll();
		System.out.println("唤醒其他阻塞状态的线程!");
	}

	/**
	 * 使用synchronize块的写法
	 */
	public void addCntK() {
		synchronized (this) {
			for (int i = 0; i < 10; i++) {
				System.out.println("当前cnt的值为:" + cnt + "当前Thread:A");
				cnt++;
				if (i == 5) {
					try {
						System.out.println("把当前A线程强制进入阻塞状态!");
						wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				try {
					Thread.sleep(300);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}

	}
}

代码执行结果:

4、本例会使用yield方法让线程自动放弃当前CPU时间

package com.abc.test4;

/**
 * @author 别说难忘记
 *
 */
public class Tester {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
	
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				for(int i =1;i<=20;i++) {
					
					System.out.println("this is one play A !"+i);	
					if(i%5==0) {
						//System.out.println("在这里自动放弃当前CPU时间");//虽然自动放弃了CPU时间,还是有概率再次继续获得CPU时间
						Thread.yield(); 
						
					}
							
				}				
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				for(int i =1;i<=20;i++) {
					System.out.println("this is one play B !"+i);
					
				}				
			}
		}).start();
	}

}

代码执行结果:

5、 这个例子将会使用join方法让线程嵌入main线程

package com.test.test5;

/**
 * @author 别说难忘记
 *
 */
public class Tesyer {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Thread t1 = new Thread(new Runnable() {
			
			@Override
			public void run() {
				
				for(int i =1;i<=20;i++) {
					System.out.println("this is one play A !"+i);	
					if(i%5==0) {	
						Thread.yield(); //在这里自动放弃当前CPU时间,虽然自动放弃了CPU时间,还是有概率再次继续获得CPU时间						
					}				
				}	
				
			}
		});
		Thread t2 = new Thread(new Runnable() {
			@Override
			public void run() {
				for(int i =1;i<=20;i++) {
					System.out.println("this is one play B !"+i);
					
				}				
			}
		});
		t1.start();
		try {
			t1.join(); //在这里吧线程t1加入mian线程,所以就会一直执行完t1线程,再执行t2线程。	
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		t2.start();
		
	}

}

代码执行结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值