在多线程的处理中,可以利用Runnable描述多个线程操作的资源,而Thread描述每一个线程对象,于是当多个线程访问同一资源的时候,如果处理不当就会产生数据的错误操作。 同步问题的引出 下面编写一个简单的卖票程序,将创建若干个线程对象实现卖票的处理操作。 范例:
1package cn.cccc.demo;2class MyThread implements Runnable{3 private int ticket = 10; //总票数为十张4 public void run(){5 while(true){6 if(this.ticket > 0 ){7 try {8 Thread.sleep(100);9 } catch (InterruptedException e) {10 // TODO Auto-generated catch block11 e.printStackTrace();12 }//模拟网络延迟13 System.out.println(Thread.currentThread().getName()+ "卖票,ticket"+ this.ticket -- );14 }else {15 System.out.println("票已卖完");13 collapsed lines
16 break;17 }18 }19 }20}21public class ThreadDemo {22 public static void main(String[] args) throws Exception {23 MyThread mt = new MyThread();24 new Thread(mt, "票贩子A").start();25 new Thread(mt, "票贩子B").start();26 new Thread(mt, "票贩子C").start();27 }28}
票贩子A卖票,ticket10 票贩子B卖票,ticket9 票贩子C卖票,ticket8 票贩子A卖票,ticket7 票贩子B卖票,ticket6 票贩子C卖票,ticket6 票贩子A卖票,ticket5 票贩子B卖票,ticket4 票贩子C卖票,ticket3 票贩子A卖票,ticket2 票贩子C卖票,ticket1 票贩子B卖票,ticket0 票已卖完 票已卖完 票贩子A卖票,ticket-1 票已卖完
线程同步:解决同步问题的关键是锁,指的是当某一个线程执行操作的时候,其他线程外面等待。synchronized关键字来实现来同步。 利用同步代码块进行处理 synchronized(同步对象){ 同步代码操作; } 一般要进行同步对象处理的时候,可以采用当前对象this进行同步 范例:利用同步代码块解决数据同步访问的问题
1package cn.cccc.demo;2class MyThread implements Runnable{3 private int ticket = 10; //总票数为十张4 public void run(){5 while(true){6 synchronized (this) { //每一次只允许一个线程进行访问7 if(this.ticket > 0 ){8 try {9 Thread.sleep(100);10 } catch (InterruptedException e) {11 // TODO Auto-generated catch block12 e.printStackTrace();13 }//模拟网络延迟14 System.out.println(Thread.currentThread().getName()+ "卖票,ticket"+ this.ticket -- );15 }else {15 collapsed lines
16 System.out.println("票已卖完");17 break;18 }19 }20 }21 }22}23public class ThreadDemo {24 public static void main(String[] args) throws Exception {25 MyThread mt = new MyThread();26 new Thread(mt, "票贩子A").start();27 new Thread(mt, "票贩子B").start();28 new Thread(mt, "票贩子C").start();29 }30}
加入同步处理之后,程序的整体性能下降了。同步实际上会造成性能的降低。
利用同步方法解决:只需要在方法定义上使用synchronized关键字即可。
1package cn.cccc.demo;2class MyThread implements Runnable{3 private int ticket = 10; //总票数为十张4 public synchronized boolean sale(){5 if(this.ticket > 0 ){6 try {7 Thread.sleep(100);8 } catch (InterruptedException e) {9 // TODO Auto-generated catch block10 e.printStackTrace();11 }//模拟网络延迟12 System.out.println(Thread.currentThread().getName()+ "卖票,ticket"+ this.ticket -- );13 return true;14 }else {15 System.out.println("票已卖完");17 collapsed lines
16 return false;17 }18 }19 public void run(){20 while(this.sale()){21 ;22 }23 }24}25public class ThreadDemo {26 public static void main(String[] args) throws Exception {27 MyThread mt = new MyThread();28 new Thread(mt, "票贩子A").start();29 new Thread(mt, "票贩子B").start();30 new Thread(mt, "票贩子C").start();31 }32}
在以后学习java类库的时候回发现,系统中许多类上使用的同步处理采用的都是同步方法。
线程死锁 死锁是在进行多线程同步的处理之中有可能产生的一种问题,所谓的死锁指的是若干个线程彼此互相等待的状态。 若干个线程访问同一资源时一定要进行同步处理,而过多的同步会造成死锁。