一、【Java】多线程与高并发

一、启动多线程的三种方式

1、继承Thread 接口类 实现 run() 方法

static class MyThred extends Thread{

 @Override

 public void run(){system.out.println("Hellow MyThread!"))}

}

 

2、继承Runnable 接口类 实现 run() 方法

static class MyThred extends Runnable{

 @Override

 public void run(){system.out.println("Hellow Run!"))}

}

 

3、通过线程池也可以启动一起线程

Executors.newCachedThread

二、线程的 Sleep_Yield_Join基本 方法

1、Sleep()

1、Thread.sleep(500);

概念:CPU没有线程概念,当前线程在这休息500毫秒,这段时间其他线程去运行。运行完后再接着回来运行

 

2、Yield()

Thread.yield();

概念:运行过程中,yield() 一下,本质上是让出一下cpu,返回 “就绪” 状态,其他线程能不能抢到不管。

 

3、Join()

 

Thread t1=new Thread(()->{

 for(int i=0;i<100;i++)

 {

 System.out.println("A"+i);

 try{

 Thread.sleep(500);

 }catch(InterrupedException e){

 e.printStackTrace();

 }

 }

});





Thread t2=new Thread(()->{

 try{

 t1.join();

 }catch(InterrupedException e){

 e.printStackTrace();

 }

});

 

概念:当运行t2线程的时候调用一下t1线程,当t1线程完成以后,回来接着调用t2线程。

 

三、线程的状态

1、java里的线程状态迁移图,都是通过JVM来管理的,通过操作系统被管理。,通过线程的getState()获取状态。

 

 

1、NEW 状态:创建了,未调用初始状态。

2、Runnable 状态:交给操作系统执行(线程调度器)

2.1、Ready:就绪状态,在CPU的等待队列里,排着队,还没运行呢,

2.2、Running:正在运行的状态,正在CPU里运行中。

3、Teminated 状态:运行结束。

4、TimedWaiting:等待状态,Thread.sleep(time),o.wait(time),t.join(time),LockSupport.parkNanos(),LockSupport.partUntill(),会进入这个状态。

5、Waitig:等待状态,o.wait(), t.join() ,LockSupport.part(),会进去这个状态

6、Blocked:阻塞状态;进入到同步代码块,没有得到锁的时候。

 

四、高并发、sysnchronized 关键字

1、多个线程访问一个资源的时候,对这个资源加锁

private int count=10;

private Object o=new Object();

public void m(){

 synchronized(o){//任何线程要想执行以下代码,必须先拿到o的锁

 count--;

 System.out.println(Thread.currentThread().getName()+"count="+count);

 }

}

 

每次new一个object很麻烦,可以锁当前对象 this

private int count=10;

public void m(){

 synchronized(this){

 count--;

 System.out.println(Thread.currentThread().getName()+"count="+count);

 }

}

 

可以简写成以下代码,一个 synchronized 方法

private int count=10;

public synchronized void m(){//任何线程要想执行以下代码,必须先拿到o的锁

 count--;

 System.out.println(Thread.currentThread().getName()+"count="+count);

}

 

静态方法也可以

 

private int count=10;

public synchronized static void m(){//这里等同于synchronized(T.class)

 count--;

 System.out.println(Thread.currentThread().getName()+"count="+count);

}



public static void mm(){

 synchronized(T.class){

 count--;

 }

}

 

五、synchronized的底层实现

1、JDK早期 synchronized 是重量级的,要向系统申请锁,很慢

2、后来JDK(1.5)改进,锁升级,原来都是找操作系统申请锁,到后期对synchronized 做了一些改进,效率高不少。

例如:synchronized(object)的时候,只有一个线程访问,是不给他加锁的,只记录线程ID(偏向锁)。如果有线程争用,就升级为(自旋锁),自旋锁 如果一个线程 旋了 10次以后 还没得到锁,则升级为(系统锁)操作系统锁。

3、只能升级锁,不能降级,例如多个线程通过争用升级到(系统锁),线程数下去以后,不会降级!!!

5、加锁代码执行时间长的情况下,线程数比较多,使用系统锁(系统锁),加锁代码执行时间短,线程数少的情况下,使用(自旋锁)。

 

六、使用synchronized注意

1、不能使用String常量、Integer、Long 等基础数据类型。

2、synchronized 锁不住空对象,空对象没有markword。

posted @ 2022-12-22 15:21  lwqblog  阅读(193)  评论(0编辑  收藏  举报