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