前言
本篇博客主要总结了,多线程与高并发相关知识,目的是提升自己技术能力同时也能帮助你。
1.线程中的run与start的区别
package com.zcw.demo.demo1;
import java.util.concurrent.TimeUnit;
/**
* @ClassName : ZCWThread
* @Description :线程中start 方法与run方法
* @Author : Zhaocunwei
* @Date: 2020-06-13 13:39
*/
public class ZCWThread {
private static class T1 extends Thread{
@Override
public void run(){
for(int i=0;i<10;i++){
try {
TimeUnit.MICROSECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("T1");
}
}
}
public static void main(String[] args) {
new T1().start();
// new T1().run();
for(int i=0;i<10;i++){
try {
TimeUnit.MICROSECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main");
}
}
}
运行结果:
通过上面两个图分析原因,当我们调用start方法时,会在调用start方法那里产生分支,这个分支和我的主程序一起执行,run方法呢,就一个执行路径。
2.创建线程的两种方式-启动线程程序的三种方式
package com.zcw.demo.demo1;
/**
* @ClassName : HowToCreateThread
* @Description :创建线程的两种方式
* @Author : Zhaocunwei
* @Date: 2020-06-13 14:15
*/
public class HowToCreateThread {
static class MyThread extends Thread{
@Override
public void run (){
System.out.println("Hello MyThread!");
}
static class MyRun implements Runnable{
@Override
public void run(){
System.out.println("Hello MyRun!");
}
public static void main(String[] args) {
new MyThread().start();
new Thread(new MyRun()).start();
new Thread(() ->{
System.out.println("Hello lambda!");
}).start();
}
}
}
}
启动线程的三种方式:
1.Thread
2.Runnable
3.Executors.newCachedThrad
3.线程中的基本方法
package com.zcw.demo.demo1;
/**
* @ClassName : Sleep_yield_Join
* @Description :线程中的基本方法
* @Author : Zhaocunwei
* @Date: 2020-06-13 14:24
*/
public class Sleep_yield_Join {
public static void main(String[] args){
//testSleep();
//testYield();
//testJoin();
}
static void testSleep(){
new Thread(()->{
for(int i=0;i<100;i++){
System.out.println("A"+i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
static void testYield(){
new Thread(()->{
for(int i=0;i<100;i++){
System.out.println("A"+i);
}
}).start();
new Thread(()->{
for(int i=0;i<100;i++){
System.out.println("------------------------B"+i);
if(i%10 == 0){
Thread.yield();
}
}
}).start();
}
static void testJoin(){
Thread t1= new Thread(()->{
for(int i=0;i<100;i++){
System.out.println("A"+i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(() ->{
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
for(int i=0; i<100; i++){
System.out.println("A"+i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
}
}
- 线程状态
package com.zcw.demo.demo1;
/**
* @ClassName : ThreadState
* @Description :
* @Author : Zhaocunwei
* @Date: 2020-06-13 14:54
*/
public class ThreadState {
static class MyThread extends Thread{
@Override
public void run(){
System.out.println(this.getState());
for (int i=0;i<10;i++){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i);
}
}
}
public static void main(String[] args) {
Thread t = new MyThread();
System.out.println(t.getState());
t.start();
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(t.getState());
}
}
4.Synchronized关键字对某个对象加锁
package com.zcw.demo.demo1;
/**
* @ClassName : MySynchronized
* @Description : Synchronized关键字对某个对象加锁
* @Author : Zhaocunwei
* @Date: 2020-06-13 15:20
*/
public class MySynchronized {
private static int count=10;
private Object o = new Object();
public void m(){
//任何线程要执行下面的代码,必须先拿到0的项
synchronized (o){
count --;
System.out.println(Thread.currentThread().getName()+" count="+count);
}
}
//考虑一下这里? synchronized(this)是否可以?
public static void mm(){
synchronized (MySynchronized.class){
count --;
}
}
}
- synchronized(Object)不能用String,常量,Integer long
- 线程同步
synchronized
1.锁的是对象不是代码
2.this xxx.class
3锁定方法,非锁定方法同时执行。
4.锁升级: 偏向锁,自旋锁,重量级锁,线程数少,自旋锁多。
操作消耗时间长,重量级锁
5.Volatile
- 保证线程可见性
- 禁止指令重排序
– DCL单例
–Double Check Lock
–Mgr06.java
package com.zcw.demo.demo2;
import java.util.concurrent.TimeUnit;
/**
* @ClassName : T
* @Description :
* @Author : Zhaocunwei
* @Date: 2020-06-15 12:22
*/
public class T {
/**volatile**/ boolean running =true;//对比一下在volatile的情况下,整个程序运行结果的区别
void m(){
System.out.println("m start");
while(running){
try {
TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("m end");
}
public static void main(String[] args) {
T t = new T();
new Thread(t::m,"t1").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
t.running=false;
}
}
- 运行结果:
m start
m end
- 单例
饿汉式:
类加载到内存中后,就实例化一个单例,JVM保证线程安全,简单实用,推荐使用,但是它的缺点是,不管用与否,类装载时就实例化,Class.forName("")
package com.zcw.demo.demo2;
/**
* @ClassName : Mgro1
* @Description :饿汉式
* @Author : Zhaocunwei
* @Date: 2020-06-15 12:44
*/
public class Mgro1 {
private static final Mgro1 INSTANCE = new Mgro1();
private Mgro1(){};
public static Mgro1 getInstance(){
return INSTANCE;
}
public void m(){
System.out.println("m");
}
public static void main(String[] args) {
Mgro1 m1 = Mgro1.getInstance();
Mgro1 m2 =Mgro1.getInstance();
System.out.println(m1==m2);
}
}
- 运行结果:
true
- 懒汉式
1.线程不安全的
package com.zcw.demo.demo2;
/**
* @ClassName : Mgr03
* @Description :
* @Author : Zhaocunwei
* @Date: 2020-06-15 12:50
*/
public class Mgr03 {
private static Mgr03 INSTANCE;
private Mgr03(){
}
public static Mgr03 getInstance(){
if(INSTANCE == null){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE= new Mgr03();
}
return INSTANCE;
}
public void m(){
System.out.println("m");
}
public static void main(String[] args) {
for(int i=0; i<10;i++){
new Thread(()->
System.out.println(Mgr03.getInstance().hashCode())
).start();
}
}
}
- 运行结果:
1899625310
524631667
860147208
653846628
101695638
315181923
810466593
319155376
1035305589
1035305589
把上面的类创建为线程安全的:
package com.zcw.demo.demo2;
/**
* @ClassName : Mgr04
* @Description : lazy loading
* 也称为懒汉式
* 虽然达到了按需初始化的目的,但是带来了线程不安全的问题,
* 可以通过synchronized解决,但也带来效率下降
* @Author : Zhaocunwei
* @Date: 2020-06-15 12:55
*/
public class Mgr04 {
private static Mgr04 INSTANCE;
private Mgr04(){
}
public static synchronized Mgr04 getInstance(){
if(INSTANCE == null){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE = new Mgr04();
}
return INSTANCE;
}
public void m(){
System.out.println("m");
}
public static void main(String[] args) {
for(int i =0;i<10;i++){
new Thread(()->{
System.out.println(Mgr04.getInstance().hashCode());
}).start();
}
}
}
- 运行结果:
554241184
554241184
554241184
554241184
554241184
554241184
554241184
554241184
554241184
554241184
- 单例模式添加volatile解决指令重排序问题
package com.zcw.demo.demo2;
/**
* @ClassName : Mgr06
* @Description :
* @Author : Zhaocunwei
* @Date: 2020-06-15 13:11
*/
public class Mgr06 {
private static volatile Mgr06 INSTANCE;
private Mgr06(){
}
public static Mgr06 getInstance(){
if(INSTANCE ==null){
synchronized (Mgr06.class){
if(INSTANCE ==null){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE = new Mgr06();
}
}
}
return INSTANCE;
}
public void m(){
System.out.println("m");
}
public static void main(String[] args) {
for(int i=0;i<100;i++){
new Thread(()->{
System.out.println(Mgr06.getInstance().hashCode());
}).start();
}
}
}
- 运行结果:
315181923
315181923
315181923
315181923
315181923
315181923
... ...
5.CAS(无锁优化 自旋)
- Compare And Swap
- 原子性
package com.zcw.demo.demo2;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @ClassName : AtomicInteger
* @Description :
* @Author : Zhaocunwei
* @Date: 2020-06-15 13:48
*/
public class MyAtomicInteger {
AtomicInteger count = new AtomicInteger(0);
void m(){
for(int i=0;i<1000;i++){
count.incrementAndGet();
}
}
public static void main(String[] args) {
MyAtomicInteger t = new MyAtomicInteger();
List<Thread> threads = new ArrayList<>();
for(int i=0;i<10;i++){
threads.add(new Thread(t::m,"thread-"+i));
}
threads.forEach((o)->o.start());
threads.forEach((o)->{
try {
o.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System.out.println(t.count);
}
}
- 运行结果:
10000
出现ABA问题
– 加version,或者添加标签解决问题
weakCompareAndSetObject