一、多线程
1、同步函数
- 银行存钱程序
/* 需求: 银行有一个金库。 有两个储户分别存300元,每次存100,存3次。 */ class Bank { int sum = 0; synchronized public void add(int n) { sum += n; System.out.println(Thread.currentThread().getName() + "..." + "sum=" + sum); } } class Cus implements Runnable { Bank b = new Bank(); public void run() { for(int x = 0; x < 3; x++) { b.add(100); } } } class MyBankDemo { public static void main(String[] args) { Cus c = new Cus(); Thread t1 = new Thread(c); Thread t2 = new Thread(c); t1.start(); t2.start(); } }
- 卖票程序。验证同步函数用的锁是:this
class Ticket implements Runnable { int tick = 100; //这个变量写在这里和写在run()方法里面,有什么区别? boolean flag = true; // Object obj = new Object(); public void run() { if(flag) { while(true) { synchronized(this) // { if(tick > 0) { try{Thread.sleep(10);} catch(Exception e){} System.out.println(Thread.currentThread().getName() + "...tick sale..." + tick--); } } } } else while(true) this.show(); // } synchronized public void show() //this { if(tick > 0) { try{Thread.sleep(10);} catch(Exception e){} System.out.println(Thread.currentThread().getName() + "...show..." + tick--); } } } class MyThisLockDemo { public static void main(String[] args) { Ticket t = new Ticket(); Thread t1 = new Thread(t); Thread t2 = new Thread(t); t1.start(); try { Thread.sleep(10); } catch (Exception e) { } t.flag = false; t2.start(); } }
2、静态同步函数
- 静态同步函数用的锁不是this了,因为静态方法中也不可以定义this。使用的锁是该方法所在类的字节码文件对象。类名.class
- 售票程序
class Ticket implements Runnable { static int tick = 100; boolean flag = true; public void run() { if(flag) { while(true) { synchronized(Ticket.class) // { if(tick > 0) { try{Thread.sleep(10);} catch(Exception e){} System.out.println(Thread.currentThread().getName() + "...tick sale..." + tick--); } } } } else while(true) show(); } synchronized public static void show() //static用的不是this锁 { if(tick > 0) { try{Thread.sleep(10);} catch(Exception e){} System.out.println(Thread.currentThread().getName() + "...show..." + tick--); } } } class MyStaticMethodDemo { public static void main(String[] args) { Ticket t = new Ticket(); Thread t1 = new Thread(t); Thread t2 = new Thread(t); t1.start(); try { Thread.sleep(10); } catch (Exception e) { } t.flag = false; t2.start(); } }
3、单例设计模式
- 懒汉式,特点:实例的延迟加载。问题:如果多线程访问时,会出现安全问题。可以加同步代码块解决,但有些低效。
- 饿汉式,懒汉式程序
//饿汉式 /* class Single { private static final Single s = new Single(); private Single(){} public static Single getInstance() { return s; } } class MySingleDemo { public static void main(String[] args) { Single s1 = Single.getInstance(); Single s2 = Single.getInstance(); System.out.println(s1 == s2); //true } } */ //懒汉式 (面试考,考N多地方) class Single { private static Single s = null; private Single(){} public static Single getInstance() //怎么验证懒汉式呢? { if(s == null) { synchronized(Single.class) { if(s == null) //--->A; s = new Single(); } } return s; } } class MySingleDemo { public static void main(String[] args) { } }
4、死锁:同步中嵌套同步。(应避免死锁)
- 卖票那个程序(死锁)
class Ticket implements Runnable { int tick = 100; boolean flag = true; Object obj = new Object(); public void run() { if(flag) { while(true) { synchronized(obj) // { show(); } } } else while(true) show(); // } synchronized public void show() // { synchronized(obj) // { if(tick > 0) { try{Thread.sleep(10);} catch(Exception e){} System.out.println(Thread.currentThread().getName() + "...show..." + tick--); } } } } class MyDeadLockDemo { public static void main(String[] args) { Ticket t = new Ticket(); Thread t1 = new Thread(t); Thread t2 = new Thread(t); t1.start(); try { Thread.sleep(10); } catch (Exception e) { } t.flag = false; t2.start(); } }
- 来个简单点的死锁程序:
class Test implements Runnable { boolean flag; Test(boolean flag) { this.flag = flag; } public void run() { if(flag) { synchronized(Lock.locka) { System.out.println("if locka"); synchronized(Lock.lockb) { System.out.println("if lockb"); } } } else { synchronized(Lock.lockb) { System.out.println("else lockb"); synchronized(Lock.locka) { System.out.println("else lockb"); } } } } } class MyLock { static Object locka = new Object(); static Object lockb = new Object(); } class MyDeadLockTest { public static void main(String[] args) { Test test1 = new Test(true); Test test2 = new Test(false); Thread t1 = new Thread(test1); Thread t2 = new Thread(test2); t1.start(); t2.start(); } }
二、线程间通信
1、线程间通信
- 其实就是多个线程在操作同一个资源,但是操作的动作不同。