Java自学代码--- 简单的线程同步和交互
package Thread_test; import charactor.hero_sycn_2; //代码含义:逐渐减少英雄hp,如果英雄hp为0,就等待英雄恢复到大于0之后再继续减少到0, //展示了线程同步和wait和notify进行线程交互 public class test_1 { public static void main(String[] args) { hero_sycn_2 hero_1 = new hero_sycn_2("hero 1",30); hero_sycn_2 hero_2 = new hero_sycn_2("hero 2",30); Thread t1= new Thread() { public void run() { for (int i = 0;i < 5;i++) { hero_1.hurt(hero_2); } } }; Thread t2= new Thread() { public void run() { for (int i = 0;i < 5;i++) { try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } hero_1.recover(hero_2); } } }; t1.start(); t2.start(); } }
package charactor; public class hero_sycn_2 { public String name; public int hp; public hero_sycn_2(String name,int hp) { this.hp = hp; this.name = name; } public synchronized void hurt(hero_sycn_2 h) { try { //为了表示攻击需要时间,每次攻击暂停500毫秒(0.5秒) Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (h.hp > 0) { h.hp -= 10; System.out.println("hurt -- hp : " + h.hp); } else { try { this.wait(); h.hp -= 10; System.out.println("hurt -- hp : " + h.hp); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public synchronized void recover(hero_sycn_2 h) { try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } h.hp += 10; System.out.println("recover -- hp : " + h.hp); this.notify(); } }
这是输出,可以看到,每次hp到了0的时候都会暂停,等待生命恢复到0以上再继续扣。(之所以hurt先执行是因为类方法被同步化了,所以hurt操作的时候recover不能动,除非hurt被wait了。
hurt -- hp : 20 hurt -- hp : 10 hurt -- hp : 0 recover -- hp : 10 hurt -- hp : 0 recover -- hp : 10 hurt -- hp : 0 recover -- hp : 10 recover -- hp : 20 recover -- hp : 30
顺便附上,这个是用java自带的线程池来实现的版本:
import java.util.concurrent.*; public class test_pool2 { //使用线程池来实现 public static void main(String[] args) { hero_sycn_2 hero_1 = new hero_sycn_2("hero 1",30); hero_sycn_2 hero_2 = new hero_sycn_2("hero 2",30); ThreadPoolExecutor threadPool= new ThreadPoolExecutor(10, 15, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()); threadPool.execute(new Runnable(){ @Override public void run() { for (int i = 0;i < 5;i++) { hero_1.hurt(hero_2); } } }); threadPool.execute(new Runnable(){ @Override public void run() { for (int i = 0;i < 5;i++) { try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } hero_1.recover(hero_2); } } }); }