一、进程:正在进行中的程序
二、线程:就是进程中一个负责程序执行的控制单元(执行路径)java
一个进程中,能够有多个执行路径,即多线程小程序
一个进程中,至少有一个执行路径。安全
(多线程其实就是多个线程中的快速切换)多线程
继承Thread类,重写run方法ide
一、JVM建立的主线程的任务都定义在了主函数中函数
二、Thread类中的run方法就是封装自定义线程任务的函数,即run方法至关于一个main方法this
package com.lee.juc; public class ThreadDemo_01 { public static void main(String[] args) { Demo demo1 = new Demo("张三"); Demo demo2 = new Demo("LeeSi"); demo1.start(); demo2.start(); System.out.println("=======结束========"); } } class Demo extends Thread{ private String name; @Override public void run() { for(int i=0;i<10;i++) { System.out.println(name+"====>"+i); } } public Demo() { super(); } public Demo(String name) { this.name = name; } }
结果:spa
================================线程
注:调用Run和Start有什么区别?code
================================
方法:
getName 获取线程名称
CurrentThread 返回当前正在执行线程的引用对象
package com.lee.juc; public class ThreadDemo_02 { public static void main(String[] args) { Demo2 d = new Demo2(); Thread t1 = new Thread(d); Thread t2 = new Thread(d); t1.start(); t2.start(); } } class Demo2 implements Runnable{ @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println(i+"====>"+Thread.currentThread().getName()); } } }
结果:
===========================
注:经过implement Runnable接口的方法
避免了单继承 extends Thread的局限性
===========================
再增长一个临时阻塞状态
需求:四个窗口共同卖100张票
一、继承Thread方法
NUM为static
package com.lee.juc; public class TicketDemo_01 { public static void main(String[] args) { Ticket_01 t1 = new Ticket_01(); Ticket_01 t2 = new Ticket_01(); Ticket_01 t3 = new Ticket_01(); Ticket_01 t4 = new Ticket_01(); t1.start(); t2.start(); t3.start(); t4.start(); } } class Ticket_01 extends Thread{ private static int NUM = 100; @Override public void run() { while(true) { if(NUM>0) { System.out.println(Thread.currentThread().getName()+"...sale.."+NUM--); }else { break; } } } }
结果:
二、实现Runnable接口
package com.lee.juc; public class TicketDemo_02 { public static void main(String[] args) { Ticket_02 ticket = new Ticket_02(); Thread t1 = new Thread(ticket); Thread t2 = new Thread(ticket); Thread t3 = new Thread(ticket); Thread t4 = new Thread(ticket); t1.start(); t2.start(); t3.start(); t4.start(); } } class Ticket_02 implements Runnable{ private int NUM = 100; @Override public void run() { while(true) { if(NUM>0) { System.out.println(Thread.currentThread().getName()+"...sale.."+NUM--); }else { break; } } } }
结果:
package com.lee.juc; public class TicketDemo_03 { public static void main(String[] args) { Ticket_03 ticket = new Ticket_03(); Thread t1 = new Thread(ticket); Thread t2 = new Thread(ticket); Thread t3 = new Thread(ticket); Thread t4 = new Thread(ticket); t1.start(); t2.start(); t3.start(); t4.start(); } } class Ticket_03 implements Runnable{ private int NUM = 100; @Override public void run() { while(true) { if(NUM>0) { //======加sleep======= try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();} System.out.println(Thread.currentThread().getName()+"...sale.."+NUM--); }else { break; } } } }
结果:
产生缘由:
①、多个线程,操做同一个共享数据
②、操做共享数据的线程代码有多条
就是将多条操做共享数据的线程代码封装起来,当有线程在执行这些代码的时候,其余线程不能够参与运算。
必需要当前线程把这些代码都执行完后,其余线程才能执行。
同步代码块的格式:
synchronized(对象){ 须要被同步的代码; }
代码:
package com.lee.juc; public class TicketDemo_03 { public static void main(String[] args) { Ticket_03 ticket = new Ticket_03(); Thread t1 = new Thread(ticket); Thread t2 = new Thread(ticket); Thread t3 = new Thread(ticket); Thread t4 = new Thread(ticket); t1.start(); t2.start(); t3.start(); t4.start(); } } class Ticket_03 implements Runnable{ private int NUM = 100; Object obj = new Object(); @Override public void run() { while(true) { //==================== synchronized (obj) { if(NUM>0) { try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();} System.out.println(Thread.currentThread().getName()+"...sale.."+NUM--); }else { break; } } //===================== } } }
结果:
同步的好处和弊端:
好处:解决了线程安全的问题
弊端:相对下降了效率
注:
必须保证多个线程使用同一个锁
需求:
两个储户去银行存钱,每一个人存3次,每次存¥100
一、未加锁的错误代码
package com.lee.juc; public class BankDemo_01 { public static void main(String[] args) { Customer cus = new Customer(); Thread t1 = new Thread(cus); Thread t2 = new Thread(cus); t1.start(); t2.start(); } } class Bank{ private int SUM; public void add(int num) { SUM = SUM +num; System.out.println("current bank count money : ==>"+SUM); } } class Customer implements Runnable{ //两人公用一个bank,因此bank提出来 private Bank bank = new Bank(); @Override public void run() { for(int i=0;i<3;i++) { bank.add(100); } } }
二、加锁,正确代码
package com.lee.juc; import org.omg.Messaging.SyncScopeHelper; public class BankDemo_01 { public static void main(String[] args) { Customer cus = new Customer(); Thread t1 = new Thread(cus); Thread t2 = new Thread(cus); t1.start(); t2.start(); } } class Bank{ private int SUM; public void add(int num) { SUM = SUM +num; System.out.println("current bank count money : ==>"+SUM); } } class Customer implements Runnable{ //两人公用一个bank,因此bank提出来 private Bank bank = new Bank(); @Override public void run() { for(int i=0;i<3;i++) { //===========加锁 synchronized(bank) { bank.add(100); } //============ } } }
或者
package com.lee.juc; public class BankDemo_01 { public static void main(String[] args) { Customer cus = new Customer(); Thread t1 = new Thread(cus); Thread t2 = new Thread(cus); t1.start(); t2.start(); } } class Bank{ private int SUM; //同步函数锁 public synchronized void add(int num) { SUM = SUM +num; System.out.println("current bank count money : ==>"+SUM); } } class Customer implements Runnable{ //两人公用一个bank,因此bank提出来 private Bank bank = new Bank(); @Override public void run() { for(int i=0;i<3;i++) { bank.add(100); } } }
结果:
一、验证是不是Object
package com.lee.juc; public class TicketDemo_04 { public static void main(String[] args) { Ticket_04 ticket = new Ticket_04(); Thread t1 = new Thread(ticket); Thread t2 = new Thread(ticket); t1.start(); try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();} ticket.flag = false; t2.start(); } } class Ticket_04 implements Runnable{ private int NUM = 100; boolean flag = true; Object obj = new Object(); @Override public void run() { if(flag) { while(true) { synchronized (obj) { if(NUM>0) { try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();} System.out.println(Thread.currentThread().getName()+"......同步代码块....."+NUM--); } } } }else { while(true) { this.sale(); } } } public synchronized void sale() { if(NUM>0) { try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();} System.out.println(Thread.currentThread().getName()+"...同步函数.."+NUM--); } } }
结果:
错误,证实不是obj
二、证实是否是this
package com.lee.juc; public class TicketDemo_04 { public static void main(String[] args) { Ticket_04 ticket = new Ticket_04(); Thread t1 = new Thread(ticket); Thread t2 = new Thread(ticket); t1.start(); try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();} ticket.flag = false; t2.start(); } } class Ticket_04 implements Runnable{ private int NUM = 100; boolean flag = true; Object obj = new Object(); @Override public void run() { if(flag) { while(true) { synchronized (this) { if(NUM>0) { try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();} System.out.println(Thread.currentThread().getName()+"......同步代码块....."+NUM--); } } } }else { while(true) { this.sale(); } } } public synchronized void sale() { if(NUM>0) { try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();} System.out.println(Thread.currentThread().getName()+"...同步函数.."+NUM--); } } }
结果:
证实是this
代码:
package com.lee.juc; public class TicketDemo_05 { public static void main(String[] args) { Ticket_05 ticket = new Ticket_05(); Thread t1 = new Thread(ticket); Thread t2 = new Thread(ticket); t1.start(); try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();} ticket.flag = false; t2.start(); } } class Ticket_05 implements Runnable{ private static int NUM = 100; boolean flag = true; Object obj = new Object(); @Override public void run() { if(flag) { while(true) { synchronized (this.getClass()) { if(NUM>0) { try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();} System.out.println(Thread.currentThread().getName()+"......同步代码块....."+NUM--); } } } }else { while(true) { this.sale(); } } } public static synchronized void sale() { if(NUM>0) { try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();} System.out.println(Thread.currentThread().getName()+"...同步函数.."+NUM--); } } }
结果:
注:
静态同步函数的锁是 当前文件的字节码,this.getClass或TicketDemo_05.class
//懒汉式 class SingleLazy{ private static SingleLazy singleLazy; private SingleLazy() {} private static SingleLazy getInstance() { if(singleLazy==null) { synchronized (SingleLazy.class) { if(singleLazy==null) { singleLazy = new SingleLazy(); } } } return singleLazy; } } //饿汉式--推荐使用这个 class SingleHungry{ private static SingleHungry singleHungry = new SingleHungry(); private SingleHungry() {} private static SingleHungry getInstance() { return singleHungry; } }
产生情景:
一、同步的嵌套:A锁里边有B锁,B锁里边有A锁。
package com.lee.juc; public class DeadLockTest { public static void main(String[] args) { DeadLock deadLock = new DeadLock();//flag = true Thread t1 = new Thread(deadLock); Thread t2 = new Thread(deadLock); t1.start(); try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();} deadLock.flag = false; t2.start(); } } class DeadLock implements Runnable{ public boolean flag = true; private Object obj = new Object(); public DeadLock() {} public DeadLock(boolean flag) { this.flag = flag; } public void run() { if(flag) { while(true) { synchronized (this) { System.out.println("...if...this...lock.."+Thread.currentThread().getName()); synchronized (obj) { System.out.println("...if...obj...lock.."+Thread.currentThread().getName()); } } } }else { while(true) { synchronized (obj) { System.out.println("...else...obj...lock.."+Thread.currentThread().getName()); synchronized (this) { System.out.println("...else...this...lock.."+Thread.currentThread().getName()); } } } } } }
结果: