Java并发编程 笔记 实验

1.线程基础

线程创建

(1)继承Thread类。
Thread 类本质上是实现了 Runnable 接口的一个实例,代表一个线程的实例。
启动线程的唯一方法 就是通过 Thread 类的 start()实例方法。
start()方法是一个 native 方法,它将启动一个新线程,并执行 run()方法。

class MyThread extends Thread{
	public  MyThread(String name) {
		this.setName(name);
	}
	@Override
	public void run() {//重写Run方法
		System.out.println(this.getName());
	}
}
public class ThreadStudy {
	public static void main(String[] args) {
		MyThread mythread=new MyThread("myThread");
		mythread.start();
	}
}

(2)实现 Runnable 接口
如果自己的类已经 extends 另一个类,就无法直接 extends Thread,此时,可以实现一个Runnable 接口。

class MyThread implements  Runnable{
	public void run() {
		System.out.println("实现了Runnable接口");
	}
}
public class ThreadStudy {
	public static void main(String[] args) {
		//注意!!!!此处需要将线程类实例传入Thread中
		Thread thread=new Thread(new MyThread());
		thread.start();
		//使用lambda表达式创建线程
		new Thread(() ->System.out.println("thread")).start();
	}
}

(3)实现Callable接口

class MyCallable implements  Callable<String>{
	@Override
	public String call() throws Exception {
		//实现Callable接口,有返回值
		return "实现了Callable";
	}
}
public class ThreadStudy {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		//创建线程池
		ExecutorService pool=Executors.newFixedThreadPool(2);
		//执行任务并获取 Future 对象
		Future<String>  future=pool.submit(new MyCallable());
		//关闭线程池
		pool.shutdown();
		//获取任务返回值
		System.out.println(future.get());	
		  
	}
}

或者不使用线程池:

		FutureTask<String> futureTask =new FutureTask<>(new myThreadCall());
		new Thread(futureTask).start();;
		System.out.println(futureTask.get());

(4)4种线程池
目的:缓存策略,节省线程创建和销毁的时间。可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
(1)newCachedThreadPool
可缓存线程池,对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。
调用 execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。
(2)newFixedThreadPool
定长线程池,无界队列。可控制线程最大并发数,超出的线程会在队列中等待。
(3)newScheduledThreadPool
定长线程池,支持周期、定时
(4)newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序。这个线程池可以在线程死后(或发生异常时)重新启动一个线程来替代原来的线程继续执行下去。

线程停止

(1)自然停止
(2)抛出异常
(3)stop()、resume()、suspend()
stop()强行终止线程,无法保证线程资源正常释放
suspend()不会释放资源,会造成死锁
(4)安全的停止:
interrupt():只是给线程一个标记,并不是真正的中断,中断标志位设置为true
isInterrupted():判断是否处于中断状态
static 方法的interrupted():判断是否处于中断状态,中断标志位设置为false
InterruptedException:抛出异常后,标志位会复位成false
ps,Java线程是协作式的

	private static class myThread extends Thread{
		@Override
		public void run() {
			String threadName=Thread.currentThread().getName();
			while(!isInterrupted()){
				System.out.println(threadName);
			}
			System.out.println("interrupt flag:"+isInterrupted());	
		}
	}

	public static void main(String[] args) throws InterruptedException, ExecutionException {
		myThread thread=new myThread();
		thread.start();
		Thread.sleep(20);
		thread.interrupt();
	}

输出:

Thread-0
....
Thread-0
interrupt flag:true

2.手写简单死锁和jstack检测

死锁1

线程1获取TestClass类锁,线程2获取Object类锁,线程1请求Object类锁,阻塞状态,线程2请求TestClass类锁,也进入阻塞状态。

package swardoffer;

class TestClass{
	
}
public class ThreadStudy {
	public static void main(String[] args)  {
		
		new Thread(()->{
			System.out.println("run1");
			synchronized (TestClass.class) {
				try {
					Thread.sleep(1000);
				} catch (Exception e) {
					e.printStackTrace();
				}
				synchronized(Object.class){
					System.out.println("block1");
				}
			}
			
		}).start();
		new Thread(()->{
			System.out.println("run2");
			synchronized (Object.class) {
				try {
					Thread.sleep(1000);
				} catch (Exception e) {
					e.printStackTrace();
				}
				synchronized(TestClass.class){
					System.out.println("block2");
				}
			}
			
		}).start();
	}
}

运行结果:
在这里插入图片描述
查看Java进程:
在这里插入图片描述
jstack -help:
在这里插入图片描述
jstack检测死锁:输入命令 jstack -l 2264
在这里插入图片描述
在这里插入图片描述

死锁2

class TestClass implements Runnable {
	Object o1=new Object();
	Object o2=new Object();
	boolean flag ;
	public TestClass(boolean flag){
		this.flag=flag;
	}
	public void run() {
		if(this.flag){
			System.out.println("run1");
			synchronized (o1) {
				try {
					Thread.sleep(1000);
				} catch (Exception e) {
					e.printStackTrace();
				}
				synchronized(o2){
					System.out.println("block1");
				}}
		}else{
			System.out.println("run2");
			synchronized (o2) {
				try {
					Thread.sleep(1000);
				} catch (Exception e) {
					e.printStackTrace();
				}
				synchronized(o1){
					System.out.println("block2");
				}
			}
		}	
	}
}
public class ThreadStudy {
	public static void main(String[] args)  {
		TestClass thread=new TestClass(true);
		new Thread(thread).start();
		thread.flag=false;
		new Thread(thread).start();
	}
}

运行结果:
可能是:未发生死锁
在这里插入图片描述
也可能是:发生死锁
在这里插入图片描述

3.Synchronized 反编译字节码文件

(1)同步代码块

public class ThreadStudy {
	Object object =new Object();
	public void fun(){
		synchronized (object) {
			
		}
	}
}

1.编译java文件,生成字节码文件
在这里插入图片描述
2. 反编译 字节码文件
在这里插入图片描述
3.
在这里插入图片描述
(2)同步方法

public class ThreadStudy {

	 synchronized void f1(){
		
	}
	static  synchronized void f(){
		
	}
}

在这里插入图片描述

4.循环打印ABC

(1)ReentrantLock 结合condition

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

class Testabc implements Runnable{	
	public String str="";
	private Condition thiscon;
	private Condition nextcon;
	private ReentrantLock lock;
	public Testabc(ReentrantLock lock,String str,Condition thiscon,Condition nextcon) {
		this.lock=lock;
		this.str=str;
		this.thiscon=thiscon;
		this.nextcon=nextcon;
	}
	@Override
	public void run() {
		lock.lock();
		for (int i = 0; i < 10; i++) {
			System.out.print(str);
			nextcon.signal();
			if(i<9){ //最后一次就不await了
				try {
					thiscon.await();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		lock.unlock();
	}	
}
public class Main {
	public static void main(String[] args) throws InterruptedException {
		ReentrantLock lock = new ReentrantLock();
        // 打印a线程的condition
        Condition conditionA = lock.newCondition();
        Condition conditionB = lock.newCondition();
        Condition conditionC = lock.newCondition();
		
        Thread A= new Thread(new Testabc(lock,"A",conditionA,conditionB));
        Thread B= new Thread(new Testabc(lock,"B",conditionB,conditionC));
        Thread C= new Thread(new Testabc(lock,"C",conditionC,conditionA));
		
		A.start();
		B.start();
		Thread.sleep(100);
		C.start();		
		Thread.sleep(100);	
	}
}

(2)信号量的方法

package swardoffer;

import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
class Testabc implements Runnable{
	private Semaphore thissph;
	private Semaphore nextsph;
	private String str;
	public Testabc(String str,Semaphore thissph,Semaphore nextsph) {
		this.str=str;
		this.thissph=thissph;
		this.nextsph=nextsph;
	}
	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			try {
				thissph.acquire();
				System.out.print(str);
				nextsph.release();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}			
}
public class Main {
	public static void main(String[] args) throws InterruptedException {
		Semaphore sphA=new Semaphore(1);
		Semaphore sphB=new Semaphore(0);
		Semaphore sphC=new Semaphore(0);
		
        Thread A= new Thread(new Testabc("A",sphA,sphB));
        Thread B= new Thread(new Testabc("B",sphB,sphC));
        Thread C= new Thread(new Testabc("C",sphC,sphA));
		
		A.start();
		B.start();
		C.start();			
	}
}

5.生产者、消费者模型

lock方法一:

package swardoffer;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

class ProductThread implements Runnable{
	private AtomicInteger count;
	private ReentrantLock lock;
	private Condition pCondition;
	private Condition cCondition;
	public ProductThread(AtomicInteger count,ReentrantLock lock,Condition pcondition,Condition cCondition) {
		this.count=count;
		this.lock=lock;
		this.pCondition=pcondition;
		this.cCondition=cCondition;
	}
	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			try {
				try {
                    Thread.sleep(1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
				lock.lock();
				while(count.intValue()==10){//已有的资源满了
					System.out.println("生产者阻塞");
					pCondition.await();
				}
				//count++;
				
				count.getAndIncrement();
				System.out.println(Thread.currentThread().getName()
                        + "生产者生产,目前总共有" + count);
				cCondition.signal();//唤醒消费者线程
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {
				lock.unlock();
			}
		}
	}	
}
class ConsumeThread implements Runnable{
	private  AtomicInteger count;
	private ReentrantLock lock;
	private Condition pCondition;
	private Condition cCondition;
	
	public ConsumeThread(AtomicInteger count,ReentrantLock lock,Condition pCondition,Condition cCondition) {
		this.count=count;
		this.lock=lock;
		this.pCondition=pCondition;
		this.cCondition=cCondition;
	}
	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			try {
				try {
                    Thread.sleep(1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
				lock.lock();
				while(count.intValue()==0){//没有资源可消耗
					System.out.println("消费者被阻塞");
					cCondition.await();
				}
				//count--;
				count.getAndDecrement();
				System.out.println(Thread.currentThread().getName()
                        + "消费者消费,目前总共有" + count);
				pCondition.signal();//唤醒生产者者线程
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {
				lock.unlock();
			}
		}
	}
	
}
public class ThreadStudy {
	public static void main(String[] args) throws InterruptedException  {
		AtomicInteger count =new AtomicInteger(0);
		ReentrantLock lock=new ReentrantLock();
		Condition pCondition=lock.newCondition();
		Condition cCondition=lock.newCondition();
		ProductThread productThread=new ProductThread(count, lock, pCondition, cCondition);
		ConsumeThread consumeThread=new ConsumeThread(count, lock, pCondition, cCondition);
		Thread.sleep(100);
		for (int i = 0; i < 10; i++) {
			new Thread(productThread).start();
			new Thread(consumeThread).start();
		}
	}
}

lock方法二:

package swardoffer;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

class ProductThread implements Runnable{
	private ReentrantLock lock;
	private Condition pCondition;
	private Condition cCondition;
	public ProductThread(ReentrantLock lock,Condition pcondition,Condition cCondition) {
		this.lock=lock;
		this.pCondition=pcondition;
		this.cCondition=cCondition;
	}
	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			try {
				try {
                    Thread.sleep(1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
				lock.lock();
				while(ThreadStudy.count==10){//已有的资源满了
					System.out.println("生产者阻塞");
					pCondition.await();
				}
				ThreadStudy.count++;

				System.out.println(Thread.currentThread().getName()
                        + "生产者生产,目前总共有" + ThreadStudy.count);
				cCondition.signal();//唤醒消费者线程
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {
				lock.unlock();
			}
		}
	}	
}
class ConsumeThread implements Runnable{
	private ReentrantLock lock;
	private Condition pCondition;
	private Condition cCondition;
	
	public ConsumeThread(ReentrantLock lock,Condition pCondition,Condition cCondition) {
		this.lock=lock;
		this.pCondition=pCondition;
		this.cCondition=cCondition;
	}
	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			try {
				try {
                    Thread.sleep(1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
				lock.lock();
				while(ThreadStudy.count==0){//没有资源可消耗
					System.out.println("消费者被阻塞");
					cCondition.await();
				}
				ThreadStudy.count--;
				System.out.println(Thread.currentThread().getName()
                        + "消费者消费,目前总共有" + ThreadStudy.count);
				pCondition.signal();//唤醒生产者者线程
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {
				lock.unlock();
			}
		}
	}
	
}
public class ThreadStudy {
	static Integer count =new Integer(0);
	public static void main(String[] args) throws InterruptedException  {
		
		ReentrantLock lock=new ReentrantLock();
		Condition pCondition=lock.newCondition();
		Condition cCondition=lock.newCondition();
		ProductThread productThread=new ProductThread(lock, pCondition, cCondition);
		ConsumeThread consumeThread=new ConsumeThread(lock, pCondition, cCondition);
		Thread.sleep(100);
		for (int i = 0; i < 10; i++) {
			new Thread(productThread).start();
			new Thread(consumeThread).start();
		}

		
		
	}

}

6.Fork/Join 框架

思想:分而治之
例子:同步方法带返回值

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
class ForkJoinTest extends RecursiveTask<Integer>{
	private static final int THRESHOLD=100;
	private int []src;
	private int formIndex;
	private int endIndex;
	public ForkJoinTest(int []src,int formIndex,int endIndex) {
		this.src=src;
		this.formIndex=formIndex;
		this.endIndex=endIndex;
	}
	@Override
	protected Integer compute() {
		if (endIndex-formIndex<THRESHOLD) {
			int sum=0;
			for (int i =formIndex;i<=endIndex;i++) {
				sum+=src[i];
			}
			return sum;
		}else{
			int mid=(formIndex+endIndex)>>1;
			ForkJoinTest left=new ForkJoinTest(src,formIndex,mid);
			ForkJoinTest right=new ForkJoinTest(src,mid+1,endIndex);
			invokeAll(left,right);
			return left.join()+right.join();
		}
	}
}
public class ThreadStudy {

	public static void main(String[] args)  {
		int src[]=new int[4000];
		for (int i = 0; i < src.length; i++) {
			src[i]=2;
		}
		ForkJoinPool forkJoinPool=new ForkJoinPool();
		ForkJoinTest task=new ForkJoinTest(src, 0, 3999);
		forkJoinPool.invoke(task);
		System.out.println(task.join());
	}

}

7.数据库连接池 Semaphare实现

class DpPoolSemaphore {
	//数据库连接池的数量
	private final static int POOL_SIZE=10;
	//可用数据库连接,已用数据库连接
	private final Semaphore usefull,useless;
	public DpPoolSemaphore(){
		this.usefull=new Semaphore(POOL_SIZE);
		this.useless=new Semaphore(0);
	}
	//存放数据库连接
	private static LinkedList<Connection> pool=new LinkedList<>();
	static{
		for (int i = 0; i < POOL_SIZE; i++) {
			pool.addLast(new MyConnection());
		}
	}
	//归还连接
	public void returnConnect(Connection connection)throws InterruptedException{
		if (connection!=null) {
			useless.acquire();//已用连接-1
			synchronized (pool) {
				pool.addLast(connection);
			}
			usefull.release();//可用连接释放资源
		}
	}
	//拿连接
	public Connection takeConnection(Connection connection)throws InterruptedException{
		usefull.acquire();//获取可用数据连接
		Connection conn;
		synchronized (pool) {
			conn=pool.removeFirst();
		}
		useless.release();//释放已用连接,已用数据连接加一
		return conn;
	} 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值