Java 之 多线程使用说明

一、线程状态

在这里插入图片描述

1.线程创建

方式一:继承Thread类,实现run方法,本质Thread类还是实现了Runnable接口。Thread作为静态代理类。

//继承Thread类
public class MyThread extends  Thread {
    @Override
    public void run() {
        //将需要完成的业务写在这里
        System.out.println("线程创建:"+Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        //创建线程
        MyThread my = new MyThread();
        //开启线程,如果调用run方法,不会创建新线程
        my.start();
//        my.run();
        System.out.println("程序结束");
    }
}

/** 调用start方法
 程序结束
 线程创建:Thread-0
 */

/**
 线程创建:main
 程序结束
 */

方式二:实现Runnable接口,重写run方法。实际使用中推荐使用

//实现接口Runnable, 常用
public class MyThreadImpl implements Runnable {
    @Override
    public void run() {
        System.out.println("线程创建: "+ Thread.currentThread().getName());
    }


    public static void main(String[] args) {
        System.out.println("程序开始");

        new Thread(new MyThreadImpl()).start();

        System.out.println("程序结束");
    }
}

/**
 程序开始
 程序结束
 线程创建: Thread-0
 */

方式三:实现Callable接口,重写call()方法

优点:

  • 定义返回值
  • 抛出异常
/**
 * 实现callable接口,可以获取线程返回值
 */
public class ThreadTest implements Callable<Boolean> {

    private String name;    //线程名字

    public ThreadTest(String name){
        this.name = name;
    }

    @Override
    public Boolean call() throws Exception {
        System.out.println("线程已经创建,线程名:"+name);
        return true;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        //创建线程
        ThreadTest t1 = new ThreadTest("1");
        ThreadTest t2 = new ThreadTest("2");

        //创建线程池
        ExecutorService service = Executors.newFixedThreadPool(2);

        //提交线程执行
        Future<Boolean> r1 =  service.submit(t1);
        Future<Boolean> r2 =  service.submit(t2);

        //获取返回结果
        System.out.println("线程1返回结果:"+r1.get());
        System.out.println("线程2返回结果:"+r2.get());

        //关闭线程池
        service.shutdown();
    }
}

线程运行

调用Thread对象的start方法即可

2.修改线程名称

如果是继承Thread类,可以添加一个带String参数的构造函数,或者使用对象调用setName()方法。

//继承Thread类
public class MyThread extends  Thread {

    public MyThread(String name){
        this.setName(name);
    }
}

如果是实现的Runnable接口,可以在创建时指定第二个参数
new Thread(new MyThreadImpl(),“MyThreadImpl”).start();

3.线程的休眠

每个对象都有一把锁,sleep并不会释放锁

try {
	Thread.sleep(1000);  //单位是毫秒
} catch (InterruptedException e) {
	e.printStackTrace();
}

4.线程的优先级

设置线程优先级意味着线程可以更大概率得到CPU时间片

//数字越大优先级越高
//Thread.MAX_PRIORITY(10) – Thread.MIN_PRIORITY(1)
my.setPriority(4);

5.线程让出当前执行权限

当前线程执行状态由运行态变为就绪态。至于是否可以让出执行权限,看CPU调度

my.yield();

6.线程停止

建议使用一个标志位来标志线程停止
一般最好让线程自己执行完毕

public class Thread1 implements  Runnable {

    private  Boolean IsStop = false;
    @Override
    public void run() {
        while (!IsStop){
            System.out.println("线程运行");
        }
    }

    public  void SetStop(Boolean flag){
        this.IsStop = flag;
        System.out.println("线程停止");
    }

    public static void main(String[] args) throws InterruptedException {
        Thread1 test = new Thread1();
        Thread t1 = new Thread(test);
        t1.start();
        int i = 1000;
        Thread.sleep(3000);
        test.SetStop(true);
    }
}

7.等待某个线程结束

    Thread1 test = new Thread1();
    Thread t1 = new Thread(test);
    t1.start();
    int i = 1000;
    Thread.sleep(3000);
    t1.join();

等待t1线程执行完毕。
一般用于main函数中等待其他线程执行结束

8.获取线程状态

线程状态枚举类

public enum State {
   /**
    * Thread state for a thread which has not yet started.
    */
   NEW,

   /**
    * Thread state for a runnable thread.  A thread in the runnable
    * state is executing in the Java virtual machine but it may
    * be waiting for other resources from the operating system
    * such as processor.
    */
   RUNNABLE,

   /**
    * Thread state for a thread blocked waiting for a monitor lock.
    * A thread in the blocked state is waiting for a monitor lock
    * to enter a synchronized block/method or
    * reenter a synchronized block/method after calling
    * {@link Object#wait() Object.wait}.
    */
   BLOCKED,

   /**
    * Thread state for a waiting thread.
    * A thread is in the waiting state due to calling one of the
    * following methods:
    * <ul>
    *   <li>{@link Object#wait() Object.wait} with no timeout</li>
    *   <li>{@link #join() Thread.join} with no timeout</li>
    *   <li>{@link LockSupport#park() LockSupport.park}</li>
    * </ul>
    *
    * <p>A thread in the waiting state is waiting for another thread to
    * perform a particular action.
    *
    * For example, a thread that has called {@code Object.wait()}
    * on an object is waiting for another thread to call
    * {@code Object.notify()} or {@code Object.notifyAll()} on
    * that object. A thread that has called {@code Thread.join()}
    * is waiting for a specified thread to terminate.
    */
   WAITING,

   /**
    * Thread state for a waiting thread with a specified waiting time.
    * A thread is in the timed waiting state due to calling one of
    * the following methods with a specified positive waiting time:
    * <ul>
    *   <li>{@link #sleep Thread.sleep}</li>
    *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
    *   <li>{@link #join(long) Thread.join} with timeout</li>
    *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
    *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
    * </ul>
    */
   TIMED_WAITING,

   /**
    * Thread state for a terminated thread.
    * The thread has completed execution.
    */
   TERMINATED;
}

获取线程状态

Thread.State state = t1.getState();

二、线程访问资源同步

import java.util.concurrent.locks.ReentrantLock;

/**
 * 同步代码
 */
public class SynchronizedStuff {

    /**
     * 同步方法的锁:
     * 静态方法是类.class
     * 非静态方法是this
     */
    public synchronized static void sale(){
        if (DataTest.tickets >0)
        {
            System.out.println("还剩:"+ DataTest.tickets-- +"张票");
        }
    }

    public static void main(String[] args) {

        //可重入锁
        ReentrantLock mylock = new ReentrantLock();

        Runnable t = new Runnable() {
            @Override
            public void run() {
                while (DataTest.tickets > 0)
                {
                    //方式一
                    synchronized (this){//需要同一把锁
                        if (DataTest.tickets >0)
                        {
                            System.out.println("还剩:"+ DataTest.tickets-- +"张票");
                        }
                    }

                    //方式二
//                    sale();

                    //方式三
//                    mylock.lock();
//                    if (DataTest.tickets >0)
//                    {
//                       System.out.println("还剩:"+ DataTest.tickets-- +"张票");
//                    }
//                    mylock.unlock();
                }
            }
        };

        new Thread(t,"Thread 0").start();
        new Thread(t,"Thread 1").start();
        new Thread(t,"Thread 2").start();
        new Thread(t,"Thread 3").start();
    }
}

class  DataTest{
    public static int tickets = 100;
}

三、线程死锁

多个线程持有对方需要的锁。相互等待造成死锁。
/**
 * 死锁示例
 */
public class DeadLock {

    public static void main(String[] args) {

        Object a = new Object();
        Object b = new Object();

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (a){
                    System.out.println("aaaa");
                    synchronized (b){
                        System.out.println("bbbbbbb");
                    }
                }
            }
        }, "Thread1");

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (b){
                    System.out.println("bbbb");
                    synchronized (a){
                        System.out.println("aaaaa");
                    }
                }
            }
        }, "Thread1");

        Thread t3 = new Thread(() ->{
                System.out.println("testllll");
            }, "Thread1");

        t1.start();
        t2.start();
//        t3.start();
    }
}

解决死锁问题

/**
 * 死锁示例
 */
public class DeadLock {

    public static void main(String[] args) {

        Object a = new Object();
        Object b = new Object();

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (a){
                    System.out.println("获取A锁");

                    try {
                        a.wait();  //释放A锁并等待
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (b){
                        System.out.println("获取A+B锁");
                    }
                }
            }
        }, "Thread1");

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (b){
                    System.out.println("获取B锁");

                    synchronized (a){
                        System.out.println("获取B+A锁");
//                        a.notify();   //通知等待的任意一个对象A
                        a.notifyAll();  //通知等待的所有对象A
                    }
                }
            }
        }, "Thread1");

        Thread t3 = new Thread(() ->{
                System.out.println("testllll");
            }, "Thread1");

        t1.start();
        t2.start();
//        t3.start();
    }
}

四、生产消费模式

生产者:
队列满了之后等待

消费者:
队列没有元素等待

//产品类
public class Production {
    private String name;

    public  Production(String name){
        this.name = name;
    }

    public void setName(String name){
        this.name = name;
    }

    public String getName(){
        return this.name;
    }
}
//消费者:
public class Consumer extends Thread {

    private ProductPool pool;

    public  Consumer(ProductPool pool){
        this.pool = pool;
    }

    @Override
    public void run() {
        while (true){
            Production production = this.pool.pop();
            System.out.println("消费了一个产品: "+production.getName());
        }
    }
}

//生产者:
public class Producer extends Thread {

    private ProductPool pool;

    public  Producer(ProductPool pool){
        this.pool = pool;
    }

    @Override
    public void run() {
        while (true){
            String name = (int)(Math.random()*100) +"产品";
            Production production = new Production(name);
            this.pool.push(production);

            System.out.println("生产了一个产品: "+production.getName());
        }
    }
}
//产品池
import java.util.LinkedList;
import java.util.List;

public class ProductPool {

    private List<Production> productList;

    private int maxSize = 0;

    public ProductPool(int maxSize){
        this.productList = new LinkedList<>();
        this.maxSize = maxSize;
    }

    public synchronized  void push(Production producttion){

        if (this.productList.size() == maxSize){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        this.productList.add(producttion);

        this.notifyAll();
    }

    public synchronized  Production pop(){

        if (this.productList.size() == 0){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        Production production  = this.productList.remove(0);

        this.notifyAll();
        return  production;
    }
}

//主程序
public class Program {
    public static void main(String[] args) {
		//产品队列
        ProductPool productPool = new ProductPool(10);
        
        //生产者、消费者共享队列
        Consumer c = new Consumer(productPool);
        Producer p = new Producer(productPool);

        p.start();
        c.start();
    }
}

五、线程池

public class ThreadTest implements Callable<Boolean> {

    private String name;    //线程名字

    public ThreadTest(String name){
        this.name = name;
    }

    @Override
    public Boolean call() throws Exception {
        System.out.println("线程已经创建,线程名:"+name);
        return true;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        //创建线程
        ThreadTest t1 = new ThreadTest("1");
        ThreadTest t2 = new ThreadTest("2");

        //创建线程池
        ExecutorService service = Executors.newFixedThreadPool(2);

        //提交线程执行
        Future<Boolean> r1 =  service.submit(t1);
        Future<Boolean> r2 =  service.submit(t2);

        service.execute(new MyThread());
        service.execute(new MyThread());

        //获取返回结果
        System.out.println("线程1返回结果:"+r1.get());
        System.out.println("线程2返回结果:"+r2.get());

        //关闭线程池
        service.shutdown();
    }
}

class MyThread implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}

Future submit(Callable task);
void execute(Runnable command);

二者接受的参数类型不一样。

发布了193 篇原创文章 · 获赞 13 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/u013919153/article/details/105434626