多线程基础

多线程基础

Process and Thread

进程:

​ 进程就是一个程序,程序就是指令与数据的有序集合,本身没有任何含义

线程:

​ 一个进程中可以存在多个线程,但是最少有一个主线程,不然就没有存在的意义

线程的创建

Thread 继承

//extends Thead class override run method
public class threadTest01 extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("study thread: " +i);
        }
    }

    public static void main(String[] args) {
        //create thread start thread
        new threadTest01().start();

        for (int i = 0; i < 20; i++) {
            System.out.println("main : " +i);
        }
    }
}

Runnable 实现

//implements Runnable Override run method
public class RunnableTest01 implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("study thread: " +i);
        }
    }

    public static void main(String[] args) {
        new Thread(new RunnableTest01()).start();

        for (int i = 0; i < 20; i++) {
            System.out.println("main : " +i);
        }
    }
}

Callable 实现 返回值 抛异常

import java.util.concurrent.*;

public class CallableTest01 implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        return 10;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService service = Executors.newFixedThreadPool(3);


        Future<Integer> result = service.submit(new CallableTest01());

        Integer integer = result.get();

        System.out.println(integer);


        service.shutdownNow();
    }
}

多线程并发操作一个对象

public class TestConcurrent implements Runnable{

    int ticketNums = 10;

    @Override
    public void run() {
        while (true){
            if (ticketNums <= 0 ){
                break;
            }
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+  "-->ticketNums: " + ticketNums--);
        }
    }

    public static void main(String[] args) {
            TestConcurrent testConcurrent = new TestConcurrent();

            new Thread(testConcurrent,"ambrose").start();
            new Thread(testConcurrent,"Makael").start();
//            new Thread(new TestConcurrent(),"Tom").start();
    }
}

image-20210209172217041

函数式接口

只有一个抽象方法的接口

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

线程的状态

源码中是6种

public enum State {
   
    NEW,     					//尚未启动的线程的线程状态

 
    RUNNABLE,					//可运行线程的线程状态。处于可运行状态的线程正在Java虚拟机中执行

 
    BLOCKED,                    //调用wait()方法进入阻塞状态

 
    WAITING,             

  
    TIMED_WAITING,

 
    TERMINATED;
}

join() 插队

//test join
public class TestJoin implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("VIP: " + i);
        }
    }


    public static void main(String[] args) {
        TestJoin testJoin = new TestJoin();

        Thread thread = new Thread(testJoin);

        thread.start();

        for (int i = 0; i < 2000; i++) {
            System.out.println("main: " + i);
            if (i == 200){
                //主线程执行到200次时,VIP线程截断执行自己
                try {
                    thread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

CopyOnWriteArrayList

集合时线程不安全的,如果需要多线程操作资源 ,可以使用juc下面的工具类

死锁

两个小孩打架互相抓着头发:

boy1: 你先放开

boy2: no 你先放

形成死锁

手持一把锁,去获取下一把

Code:

//死锁
public class DeadLock {
    public static void main(String[] args) {
        Boy boy = new Boy();
        Thread thread1 = new Thread(boy,"boy1");
        Thread thread2 = new Thread(boy,"boy2");


        thread1.start();
        thread2.start();
    }

}

class key1{

}

class key2{

}

class Boy implements Runnable{
    @Override
    public void run() {
       if (Thread.currentThread().getName().equals("boy1")){
           synchronized (key1.class){
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }

               System.out.println(Thread.currentThread().getName() + ": get key1 lock");
               synchronized (key2.class){
                   System.out.println(Thread.currentThread().getName() + ": get key2 lock");
               }
           }
       }

        if (Thread.currentThread().getName().equals("boy2")){
            synchronized (key2.class){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println(Thread.currentThread().getName() + ": get key2 lock");
                synchronized (key1.class){
                    System.out.println(Thread.currentThread().getName() + ": get key1 lock");
                }
            }
        }

    }
}

死锁产生的条件

  • 互斥条件:一个资源只能被一个进程使用
  • 一个进程因请求阻塞,对已经获得的资源保持不放
  • 进程获得资源,在未使用完之前,不能强行剥夺
  • 循环等待条件

显示定义同步锁

ReentrantLock 可重入锁

显示定义锁的代码块

import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockTest {

    public static void main(String[] args) {
        ArrayList<Object> objects = new ArrayList<>();

        ReentrantLock reentrantLock = new ReentrantLock();

        for (int i = 0; i < 10000; i++) {
            new Thread(()->{
                //加锁
                reentrantLock.lock();
                objects.add(Thread.currentThread().getName());
                //解锁
                reentrantLock.unlock();
            }).start();
        }

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(objects.size());
    }
}
posted @ 2021-02-09 20:51  immortal_mode  阅读(65)  评论(0)    收藏  举报