一、JUC系列之---线程基础

1、多线程概述

一、进程:正在进行中的程序
二、线程:就是进程中一个负责程序执行的控制单元(执行路径)java

一个进程中,能够有多个执行路径,即多线程小程序

一个进程中,至少有一个执行路径。安全

(多线程其实就是多个线程中的快速切换)多线程

2、多线程的建立方式①--继承Thread类

继承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  返回当前正在执行线程的引用对象

3、多线程的建立方式②--实现Runnable接口

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的局限性

===========================

 

4、线程状态

再增长一个临时阻塞状态

5、卖票小程序

需求:四个窗口共同卖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;
			}
		}
	}
	
}

结果:

6、线程安全问题现象

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;
			}
		}
	}
	
}

结果:

产生缘由:

①、多个线程,操做同一个共享数据

②、操做共享数据的线程代码有多条

7、同步代码块

就是将多条操做共享数据的线程代码封装起来,当有线程在执行这些代码的时候,其余线程不能够参与运算。

必需要当前线程把这些代码都执行完后,其余线程才能执行。

同步代码块的格式:

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;
				}
			}
            //=====================
			
		}
	}
	
}

结果:

同步的好处和弊端:

好处:解决了线程安全的问题

弊端:相对下降了效率

注:

必须保证多个线程使用同一个锁

8、同步函数

需求:

两个储户去银行存钱,每一个人存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);
		}
	}
	
}

结果:

9、验证同步函数的锁

一、验证是不是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

10、验证静态同步函数的锁

代码:

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

11、单例模式

//懒汉式
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;
	}
	
}

12、死锁的情景

产生情景:

一、同步的嵌套: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());
					}
				}
			}
			
		}
		
		
	}
	
}

结果:

相关文章
相关标签/搜索