java——多线程2

java——多线程2

1.线程局部变量的共享

1.1共享一个变量的情况

使用Map集合(键值对),key放线程对象,value放共享的数据

代码实现:
package com.dream.thread01;

import java.util.concurrent.ConcurrentHashMap;

public class Test01 {
	
	public static ConcurrentHashMap<Thread, Integer> map = new ConcurrentHashMap<>();
	
	public static void main(String[] args) {
	
		new Thread(new Runnable() {
			@Override
			public void run() {
				int i = 10;
				
				//存数据
				map.put(Thread.currentThread(), i);
				
				A a = new A();
				B b = new B();
				a.println();//10
				b.println();//10
			}
		},"线程1").start();
		
		new Thread(new Runnable() {
			@Override
			public void run() {
				int i = 20;
				
				//存数据
				map.put(Thread.currentThread(), i);
				
				A a = new A();
				B b = new B();
				a.println();//20
				b.println();//20
			}
		},"线程2").start();
		
	}
}

package com.dream.thread01;

public class A {
	
	public void println(){
		Thread thread = Thread.currentThread();
		Integer value = Test01.map.get(thread);
		System.out.println(thread.getName() + "中的A类对象调用了println() -- " + value);
	}

}

package com.dream.thread01;

public class B {
	
	public void println(){
		Thread thread = Thread.currentThread();
		Integer value = Test01.map.get(thread);
		System.out.println(thread.getName() + "中的B类对象调用了println() -- " + value);
	}

}

1.2共享多个变量的情况

创建一个实体类进行存储共享的数据

代码实现:
package com.dream.thread02;

public class A {
	
	public void println(){
		Thread thread = Thread.currentThread();
		Data value = Test01.map.get(thread);
		System.out.println(thread.getName() + "中的A类对象调用了println() -- " + value);
	}

}

package com.dream.thread02;

public class B {
	
	public void println(){
		Thread thread = Thread.currentThread();
		Data value = Test01.map.get(thread);
		System.out.println(thread.getName() + "中的B类对象调用了println() -- " + value);
	}

}

package com.dream.thread02;

//数据包类
public class Data {
	
	private int i;
	private String str;
	
	public Data() {
	}

	public Data(int i, String str) {
		this.i = i;
		this.str = str;
	}

	public int getI() {
		return i;
	}

	public void setI(int i) {
		this.i = i;
	}

	public String getStr() {
		return str;
	}

	public void setStr(String str) {
		this.str = str;
	}

	@Override
	public String toString() {
		return "Data [i=" + i + ", str=" + str + "]";
	}
}

package com.dream.thread02;

import java.util.concurrent.ConcurrentHashMap;

public class Test01 {
	
	public static ConcurrentHashMap<Thread, Data> map = new ConcurrentHashMap<>();
	
	public static void main(String[] args) {

		new Thread(new Runnable() {
			@Override
			public void run() {
				
				Data data = new Data(10,"aaa");
				
				//存数据
				map.put(Thread.currentThread(), data);
				
				A a = new A();
				B b = new B();
				a.println();//10
				b.println();//10
			}
		},"线程1").start();
		
		new Thread(new Runnable() {
			@Override
			public void run() {
				Data data = new Data(20,"bbb");
				
				//存数据
				map.put(Thread.currentThread(), data);
				
				A a = new A();
				B b = new B();
				a.println();//20
				b.println();//20
			}
		},"线程2").start();	
	}
}

1.3共享多个变量的情况 - ThreadLocal

代码实现:
package com.dream.thread03;

//数据包类
public class Data {
	
	private int i;
	private String str;
	
	private Data() {
	}

	private Data(int i, String str) {
		this.i = i;
		this.str = str;
	}
	
	//获取数据包的对象
	public static Data getInstance(int i,String str){
		Data data = Test01.local.get();
		if(data == null){
			data = new Data(i, str);
			Test01.local.set(data);
		}else{
			data.setI(i);
			data.setStr(str);
		}
		return data;
	}

	public int getI() {
		return i;
	}

	public void setI(int i) {
		this.i = i;
	}

	public String getStr() {
		return str;
	}

	public void setStr(String str) {
		this.str = str;
	}

	@Override
	public String toString() {
		return "Data [i=" + i + ", str=" + str + "]";
	}
}

package com.dream.thread03;

public class Test01 {
	
	public static ThreadLocal<Data> local = new ThreadLocal<>();
	
	public static void main(String[] args) {

		new Thread(new Runnable() {
			@Override
			public void run() {
				
				Data data = Data.getInstance(10,"aaa");
				
				//存数据
				local.set(data);
				
				A a = new A();
				B b = new B();
				a.println();//10
				b.println();//10
			}
		},"线程1").start();
		
		new Thread(new Runnable() {
			@Override
			public void run() {
				Data data = Data.getInstance(20,"bbb");
				
				//存数据
				local.set(data);
				
				A a = new A();
				B b = new B();
				a.println();//20
				b.println();//20
			}
		},"线程2").start();
		
	}
}

2.synchronized琐

2.1synchronized同步代码块

需求:
package com.dream.thread04_type01;

public class Test01 {
	
	public static void main(String[] args) {
		/*
		 2.铁道部发布了一个售票任务,要求销售1000张票,要求有3个窗口来进行销售,
		  请编写多线程程序来模拟这个效果
				窗口001正在销售第1000张票
				窗口001正在销售第999张票
				窗口002正在销售第998张票
				。。。
				窗口002正在销售第1张票
				
			问题1:三个窗口都卖了1000张票,一共卖了3000张
			出现原因:三个线程调用三次run方法,就有3*1000张票
			解决方案:三个线程共用同一个票的变量
			
			问题2:有些票卖了重票
			出现原因:票的输出语句输出后,还没有来得及做票的减减,就被其他线程抢到CPU资源了
			解决方案:票的输出语句 和 票的减减必须同时执行完毕后,才能被其他线程抢到CPU资源了 - 加锁
			
			问题3:出现负数
			出现原因: 票到了零界点(ticket=1),三个线程都进入循环中
			解决方案:锁中再判断一次

			锁对象:多个线程要想互斥住,就必须使用同一把锁
		*/
		MyThread t1 = new MyThread("窗口001");
		MyThread t2 = new MyThread("窗口002");
		MyThread t3 = new MyThread("窗口003");
		
		t1.start();
		t2.start();
		t3.start();
		
		
	}
}

package com.dream.thread04_type01;

public class MyThread extends Thread{
	
	private static int ticket = 1000;
	private static Object obj = new Object();
	
	public MyThread(String name) {
		super(name);
	}

	@Override
	public void run() {
		
		while(ticket > 0){
			//synchronized("abc"){
			//synchronized(Character.class){
			synchronized(obj){
				if(ticket > 0){
					System.out.println(Thread.currentThread().getName() + "正在销售第" + ticket + "张票");
					ticket--;
				}
				if(ticket <= 0){
					System.out.println(Thread.currentThread().getName() + "票已售完");
				}
			}
		}
	}
}

2.2synchronized同步方法

package com.dream.thread04_type02;

public class Test01 {
	
	public static void main(String[] args) {
		/*
		 2.铁道部发布了一个售票任务,要求销售1000张票,要求有3个窗口来进行销售,
		 请编写多线程程序来模拟这个效果
				窗口001正在销售第1000张票
				窗口001正在销售第999张票
				窗口002正在销售第998张票
				。。。
				窗口002正在销售第1张票
				
			问题1:三个窗口都卖了1000张票,一共卖了3000张
			出现原因:三个线程调用三次run方法,就有3*1000张票
			解决方案:三个线程共用同一个票的变量
			
			问题2:有些票卖了重票
			出现原因:票的输出语句输出后,还没有来得及做票的减减,就被其他线程抢到CPU资源了
			解决方案:票的输出语句 和 票的减减必须同时执行完毕后,才能被其他线程抢到CPU资源了 - 加锁
			
			问题3:出现负数
			出现原因: 票到了零界点(ticket=1),三个线程都进入循环中
			解决方案:锁中再判断一次
			
			锁对象:多个线程要想互斥住,就必须使用同一把锁
			1.synchronized
				同步代码块:
					synchronized(锁对象){//自动上锁
						...要互斥住的代码...
					}//自动解锁
				同步方法:
					//锁对象:this
					public synchronized void method01(){//自动上锁
						...要互斥住的代码...
					}//自动解锁
					
					//锁对象:类的字节码文件对象
					public static synchronized void method02(){//自动上锁
						...要互斥住的代码...
					}//自动解锁
				
		 */
		
		MyThread t1 = new MyThread("窗口001");
		MyThread t2 = new MyThread("窗口002");
		MyThread t3 = new MyThread("窗口003");
		
		t1.start();
		t2.start();
		t3.start();
		
		
	}
}

package com.dream.thread04_type02;

public class MyThread extends Thread{
	
	private static int ticket = 1000;
	
	public MyThread(String name) {
		super(name);
	}

	@Override
	public void run() {
		
		while(ticket > 0){
			method02();
		}
	}
	
	//锁对象:类的字节码文件对象(MyThread.class)
	public static synchronized void method02(){
		if(ticket > 0){
			System.out.println(Thread.currentThread().getName() + "正在销售第" + ticket + "张票");
			ticket--;
		}
		if(ticket <= 0){
			System.out.println(Thread.currentThread().getName() + "票已售完");
		}
	}
	
	//锁对象:this
	public synchronized void method01(){
		if(ticket > 0){
			System.out.println(Thread.currentThread().getName() + "正在销售第" + ticket + "张票");
			ticket--;
		}
		if(ticket <= 0){
			System.out.println(Thread.currentThread().getName() + "票已售完");
		}
	}
}

3.Lock琐

需求:

package com.dream.thread04_type03;

public class Test01 {
	
	public static void main(String[] args) {
		/**
		 2.铁道部发布了一个售票任务,要求销售1000张票,要求有3个窗口来进行销售,
		 请编写多线程程序来模拟这个效果
				窗口001正在销售第1000张票
				窗口001正在销售第999张票
				窗口002正在销售第998张票
				。。。
				窗口002正在销售第1张票
				
			问题1:三个窗口都卖了1000张票,一共卖了3000张
			出现原因:三个线程调用三次run方法,就有3*1000张票
			解决方案:三个线程共用同一个票的变量
			
			问题2:有些票卖了重票
			出现原因:票的输出语句输出后,还没有来得及做票的减减,就被其他线程抢到CPU资源了
			解决方案:票的输出语句 和 票的减减必须同时执行完毕后,才能被其他线程抢到CPU资源了 - 加锁
			
			问题3:出现负数
			出现原因: 票到了零界点(ticket=1),三个线程都进入循环中
			解决方案:锁中再判断一次
			
			锁对象:多个线程要想互斥住,就必须使用同一把锁
					
			Lock
				Lock lock = new ReentrantLock();
				lock.lock();//手动上锁
				...要互斥住的代码...
				lock.unlock();//手动解锁
				
			synchronized vs Lock
			synchronized:关键字层面上的锁,自动上锁和自动解锁
			Lock:API层面上的锁,手动上锁和手动解锁
		 */
		
		MyThread t1 = new MyThread("窗口001");
		MyThread t2 = new MyThread("窗口002");
		MyThread t3 = new MyThread("窗口003");
		
		t1.start();
		t2.start();
		t3.start();
	}
}

package com.dream.thread04_type03;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MyThread extends Thread{
	
	private static int ticket = 1000;
	private static Lock lock = new ReentrantLock();
	
	public MyThread(String name) {
		super(name);
	}

	@Override
	public void run() {
		
		while(ticket > 0){
			lock.lock();//手动上锁
			if(ticket > 0){
				System.out.println(Thread.currentThread().getName() + "正在销售第" + ticket + "张票");
				ticket--;
			}
			if(ticket <= 0){
				System.out.println(Thread.currentThread().getName() + "票已售完");
			}
			lock.unlock();//手动解锁
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值