Java应用编程_多线程(基本知识&同步与死锁&生产者消费者模型&守护进程...)

总览

在这里插入图片描述

其他文章链接

【Java编程基础_注解与命名规则&数据类型&运算符&修饰符&流程控制】
【Java面向对象编程_方法&类与对象&数组&String类】
【Java面向对象编程_抽象类&接口&包装类&泛型】
【Java面向对象编程_包&访问控制权限&构造方法私有化&枚举】
【Java面向对象编程_异常的捕获与处理】
【Java面向对象编程_内部类】



1,进程与线程,与多线程有关的类

在这里插入图片描述

demo_多线程接口使用

package cn.thread.demo;
import java.util.concurrent.*;
//版本1:利用Thread类定义多线程主体类
//class MyThread extends Thread{
//	private String title;
//	public MyThread(String title){
//		this.title=title;
//	}
//	@Override
//	public void run() {
//		for (int i = 0; i < 10; i++) {
//			System.out.println(this.title+",x="+i);
//		}
//	}
//}
//版本2.0:利用Runnable函数式接口定义多线程主体类
//class MyRunnable implements Runnable{
//	private String name;
//	
//	public MyRunnable(String name) {
//		super();
//		this.name = name;
//	}
//
//	@Override
//	public void run() {
//		for (int i = 0; i < 10; i++) {
//			System.out.println(name+",x="+i);
//		}
//	}
//}
//版本3:利用Callable接口来定义线程主体类
class MyMath implements Callable<String>{
	@Override
	public String call() throws Exception {
		for (int j = 0; j < 10; j++) {
			System.out.println("x="+j);
		}
		return "线程结束";
	}
}


public class ThreadDemo {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
//版本1:客户端启动多线程对象
//		new MyThread("线程1").start();
//		new MyThread("线程2").start();
//		new MyThread("程序3").start();
//版本2.0:客户端利用Thread构造方法接收Runnable类的特性启动多线程对象
//		new Thread(new MyRunnable("线程1")).start();
//		new Thread(new MyRunnable("线程2")).start();
//		new Thread(new MyRunnable("线程3")).start();
//		new Thread(new MyRunnable("线程4")).start();
//版本2.1:Runnable函数式接口可以用Lambda来简化定义
//		for(int i=1;i<4;i++){
//			String title="线程"+i;
//			Runnable ru=()->{
//				for (int j = 0; j < 10; j++) {
//					System.out.println(title+",x="+j);
//				}
//			};	
//			new Thread(ru).start();
//		}
//版本2.2:进一步用Lambda简化定义,public Thread(Runnable run)
//		for (int i = 1; i < 4; i++) {
//			String title="线程"+i;
//			new Thread(()->{
//				for (int j = 0; j < 10; j++) {
//					System.out.println(title+",x="+j);
//				}				
//			}).start();
//		}
//版本3:Callable
		FutureTask<String> task =new FutureTask<>(new MyMath());
		new Thread(task).start();
		System.out.println("返回信息:"+task.get());
	}

}

2,多线程运行状态,Thread类中多线程常用操作方法

在这里插入图片描述

demo_线程常用操作1

package cn.thread.demo;

public class 线程常用操作 {

	public static void main(String[] args) {
		System.out.println("程序开始执行");
//		long data=0;
//		for (int i = 0; i < Integer.MAX_VALUE; i++) {
//			data+=i;
//		}
//通过子线程来运行运算时间长的代码块,主线程运行整体代码块来实现程序不延迟的效果
		new Thread(()->{
			long data=0;
			for (int i = 0; i < Integer.MAX_VALUE; i++) {
				data+=i;
			}
			System.out.println(Thread.currentThread().getName());
			try {
				Thread.sleep(1000);
			} catch (Exception e) {
				e.printStackTrace();
			}
			System.out.println("线程执行结束");
		},"线程1").start();

		System.out.println("程序结束执行");

	}
}

运行结果(不唯一)

程序开始执行
程序结束执行
线程1
线程执行结束

demo_线程常用操作2

package cn.thread.demo;

public class 线程相关操作 {

	public static void main(String[] args)throws Exception {
		Thread main=Thread.currentThread();
		Thread thread=new Thread(()->{
			for (int i = 0; i <50; i++) {
				if(i<=7){
					Thread.yield();//子线程礼让主线程
					System.out.println("子线程礼让");
				}
				if(i>=10){
					try {
						main.join();//main线程强制执行
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
					System.out.println("子线程x="+i);
				
			}
		});
		thread.setPriority(Thread.MAX_PRIORITY);
		thread.start();
		
		for(int x=0;x<50;x++){
			System.out.println("主线程执行:主线程x="+x);
		}

	}

}

运行结果(不唯一)

子线程礼让
主线程执行:主线程x=0
子线程x=0
子线程礼让
主线程执行:主线程x=1
子线程x=1
子线程礼让
主线程执行:主线程x=2
子线程x=2
子线程礼让
主线程执行:主线程x=3
子线程x=3
子线程礼让
主线程执行:主线程x=4
子线程x=4
子线程礼让
主线程执行:主线程x=5
子线程x=5
子线程礼让
主线程执行:主线程x=6
子线程x=6
子线程礼让
主线程执行:主线程x=7
子线程x=7
主线程执行:主线程x=8
子线程x=8
主线程执行:主线程x=9
子线程x=9
主线程执行:主线程x=10
主线程执行:主线程x=11
主线程执行:主线程x=12
主线程执行:主线程x=13
主线程执行:主线程x=14
主线程执行:主线程x=15
主线程执行:主线程x=16
主线程执行:主线程x=17
主线程执行:主线程x=18
主线程执行:主线程x=19
主线程执行:主线程x=20
主线程执行:主线程x=21
主线程执行:主线程x=22
主线程执行:主线程x=23
主线程执行:主线程x=24
主线程执行:主线程x=25
主线程执行:主线程x=26
主线程执行:主线程x=27
主线程执行:主线程x=28
主线程执行:主线程x=29
主线程执行:主线程x=30
主线程执行:主线程x=31
主线程执行:主线程x=32
主线程执行:主线程x=33
主线程执行:主线程x=34
主线程执行:主线程x=35
主线程执行:主线程x=36
主线程执行:主线程x=37
主线程执行:主线程x=38
主线程执行:主线程x=39
主线程执行:主线程x=40
主线程执行:主线程x=41
主线程执行:主线程x=42
主线程执行:主线程x=43
主线程执行:主线程x=44
主线程执行:主线程x=45
主线程执行:主线程x=46
主线程执行:主线程x=47
主线程执行:主线程x=48
主线程执行:主线程x=49
子线程x=10
子线程x=11
子线程x=12
子线程x=13
子线程x=14
子线程x=15
子线程x=16
子线程x=17
子线程x=18
子线程x=19
子线程x=20
子线程x=21
子线程x=22
子线程x=23
子线程x=24
子线程x=25
子线程x=26
子线程x=27
子线程x=28
子线程x=29
子线程x=30
子线程x=31
子线程x=32
子线程x=33
子线程x=34
子线程x=35
子线程x=36
子线程x=37
子线程x=38
子线程x=39
子线程x=40
子线程x=41
子线程x=42
子线程x=43
子线程x=44
子线程x=45
子线程x=46
子线程x=47
子线程x=48
子线程x=49

Process finished with exit code 0

3,线程的同步与死锁

在这里插入图片描述

demo_线程同步

package cn.thread.demo;
class MyThread implements Runnable{
	private int ticket=10;
	@Override
	public void run() {
		for (int i=0;i<5;i++){//假设每个票贩子有买5次票的能力
			synchronized(this){
				while (true) {
					if(this.ticket>0){
						try {
							Thread.sleep(100);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						System.out.println(Thread.currentThread().getName()+",卖票,ticket="+this.ticket--);
						break;
					}else{
						System.out.println(Thread.currentThread().getName()+"票卖完了");
						break;
					}
				}
			}
		}
	}
}
	
public class 线程同步操作 {

	public static void main(String[] args) {
		MyThread mt=new MyThread();
		new Thread(mt,"票贩子1").start();
		new Thread(mt,"票贩子2").start();
		new Thread(mt,"票贩子3").start();
	}

}

demo_线程死锁

package cn.thread.demo;
public class 死锁案例 {
    private static String resource_a = "A";
    private static String resource_b = "B";

    public static void main(String[] args) {
        deadLock();
    }

    public static void deadLock() {
        Thread threadA = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (resource_a) {
                    System.out.println(Thread.currentThread().getName()+"get resource a");
                    try {
                        Thread.sleep(3000);
                        synchronized (resource_b) {
                            System.out.println(Thread.currentThread().getName()+"get resource b");
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        },"线程1");
        Thread threadB = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (resource_b) {
                    System.out.println(Thread.currentThread().getName()+"get resource b");
                    synchronized (resource_a) {
                        System.out.println(Thread.currentThread().getName()+"get resource a");
                    }
                }
            }
        },"线程2");
        threadA.start();
        threadB.start();

    }
}

运行结果

线程2get resource b
线程1get resource a
(程序停滞)

4,案例:生产者消费者模型

在这里插入图片描述

demo_生产者消费者模型

//数据不匹配问题:同步方法解决,数据重复操作问题:线程等待与唤醒解决
package cn.thread.demo;
public class 生产者消费者模型 {
	public static void main(String[] args) {
		Message msg=new Message();
		new Thread(new Producer(msg)).start();
		new Thread(new Consumer(msg)).start();
	}
}
class Message{
	private String title;
	private String content;
	private boolean flag=true;
	//true=生产者生产,false=消费者消费
	public synchronized String get() {
		if(flag==true){
			try {
				super.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		flag=true;
		super.notify();
		return this.title+"--"+this.content;
	}
	public synchronized void set(String title,String content) {
		if(flag==false){
			try {
				super.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.title = title;
		this.content=content;
		flag=false;
		super.notify();
	}
}
class Producer implements Runnable{
	private Message msg;
	
	public Producer(Message msg) {
		super();
		this.msg = msg;
	}

	@Override
	public void run() {
		for (int i = 0; i < 50; i++) {
			if(i%2==0){
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				msg.set("偶数标题","偶数内容");
			}else{
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				msg.set("奇数标题","奇数内容");
			}
		}
	}
}
class Consumer implements Runnable{
	private Message msg;
	public Consumer(Message msg) {
		super();
		this.msg = msg;
	}
	@Override
	public void run() {
		for(int i=0;i<50;i++){
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(msg.get());
		}
	}	
}

运行结果

偶数标题--偶数内容
奇数标题--奇数内容
偶数标题--偶数内容
奇数标题--奇数内容
偶数标题--偶数内容
奇数标题--奇数内容
偶数标题--偶数内容
奇数标题--奇数内容
(重复以上内容50次)

5,优雅地停止线程

在这里插入图片描述

demo_优雅地停止线程

package cn.thread.demo;
public class 优雅地停止线程 {
	private static boolean flag=true;
	public static int count=0;
	public static void main(String[] args) {
		new Thread(()->{
			while(flag){
				System.out.println("线程运行"+(++count));
			}
		}).start();
		try {
			Thread.sleep(12);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		flag=false;
	}

}

运行结果(不唯一)

线程运行1
线程运行2
线程运行3
线程运行4
线程运行5
(重复内容...)
线程运行63

Process finished with exit code 0

6,后台守护线程

在这里插入图片描述

demo_守护线程

package cn.thread.demo;

public class 守护线程 {

	public static void main(String[] args) {
		Thread thread= new Thread(()->{
			for (int i = 0; i < 2; i++) {
				try {
					Thread.sleep(100);
				} catch (Exception e) {
					e.printStackTrace();
				}
				System.out.println("用户线程");
			}
		});
		Thread daemonthread=new Thread(()->{
			for (int i = 0; i < Integer.MAX_VALUE; i++) {
				try {
					Thread.sleep(100);
				} catch (Exception e) {
					e.printStackTrace();
				}
				System.out.println("守护线程");
			}
		});
		daemonthread.setDaemon(true);
		thread.start();
		daemonthread.start();
	}

}

运行结果

守护线程
用户线程
用户线程
守护线程

Process finished with exit code 0

7,volatile关键字

在这里插入图片描述

demo_volatile关键字

package cn.thread.demo;
class MyThreadB implements Runnable{
	private volatile int ticket=5;
	@Override
	public void run() {
		synchronized (this){
			while(true){
				if(ticket>0){
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName()+",ticket="+this.ticket--);
				}else{
					System.out.println(Thread.currentThread().getName()+"票卖完了");
					break;
				}
			}
		}
	}
}
public class Volatile关键字 {
	public static void main(String[] args)throws Exception {
		MyThreadB mt=new MyThreadB();
		new Thread(mt,"票贩子1").start();
		new Thread(mt,"票贩子2").start();
		new Thread(mt,"票贩子3").start();
	}

}

运行结果

票贩子1,ticket=5
票贩子1,ticket=4
票贩子1,ticket=3
票贩子1,ticket=2
票贩子1,ticket=1
票贩子1票卖完了
票贩子3票卖完了
票贩子2票卖完了

Process finished with exit code 0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值