创立和启动线程的形式一

  • 自定义类继承Thread类并重写run办法,而后创立该类的对象调用start办法。

创立和启动线程的形式二

  • 自定义类实现Runnable接口并重写run办法,创立该类的对象作为实参来结构Thread类型的对象,而后应用Thread类型的对象调用start办法。
public static void main(String[] args) {    new Thread(){        @Override        public void run() {            System.out.println("t1");        }    }.start();    new Thread(new Runnable() {        @Override        public void run() {            System.out.println("t2");        }    }).start();    new Thread(()->{        System.out.println("t3");    }).start();}

1.继承形式治理线程编号和名称

public class ThreadIdNameTest extends Thread{    public ThreadIdNameTest(String sun) {        //调用父类的构造方法        super(sun);    }    @Override    public void run() {        System.out.println("子线程的ID:" + this.getId());        System.out.println("子线程的名称:" + getName());    }    public static void main(String[] args) {        ThreadIdNameTest t1 = new ThreadIdNameTest("sun");        t1.start();        System.out.println("主线程的ID:" + Thread.currentThread().getId());        System.out.println("主线程的名称:" + Thread.currentThread().getName());    }}===========主线程的ID:1子线程的名称:sun主线程的名称:main

2.接口的形式治理线程编号和名称

public class MainTest {    public static void main(String[] args) {        new Thread(()->{            System.out.println("子线程的ID:" + Thread.currentThread().getId());            System.out.println("子线程的名称:" + Thread.currentThread().getName());            Thread.currentThread().setName("tttt");            System.out.println("子线程的名称:" + Thread.currentThread().getName());        }).start();        System.out.println("主线程的ID:" + Thread.currentThread().getId());        System.out.println("主线程的名称:" + Thread.currentThread().getName());    }}===========子线程的ID:14主线程的ID:1子线程的名称:Thread-0主线程的名称:main子线程的名称:tttt

3.罕用的办法

  • Sleep

public class ThreadSleepTest extends Thread {    private boolean flag = true;    @Override    public void run() {        while (flag) {            LocalDateTime now = LocalDateTime.now();            String time = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:ss:mm"));            System.out.println(time);            try {                Thread.sleep(1000);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }    public static void main(String[] args) {        ThreadSleepTest t1 = new ThreadSleepTest();        t1.start();        try {            Thread.sleep(5000);        } catch (InterruptedException e) {            e.printStackTrace();        }        t1.flag = false;    }}
  • 守护线程

public class ThreadDaemonTest extends Thread{    @Override    public void run() {        //默认不是守护线程        //当子线程不是守护线程时,尽管主线程先完结了,然而子线程仍然会继续执行,直到打印所有数据为止        //当子线程是守护时,当主线程完结后,则子线程随之完结        for(int i = 0;i < 50;i++){            System.out.println("子线程:i = "+ i);        }    }    public static void main(String[] args) {        ThreadDaemonTest t1 = new ThreadDaemonTest();        //必须在线程启动之前设置子线程为守护线程        t1.setDaemon(true);        t1.start();        for(int i = 0;i < 20;i++){            System.out.println("主线程:i = "+ i);        }    }}
  • join期待该线程终止

/** * @Author 振帅 * @Date 2021/05/26 21:49 */public class ThreadJoinTest {    public static void main(String[] args) {        //偶数        Thread t1 = new Thread(()->{            for(int i = 0;i < 100;i += 2){                System.out.println("ti==:" + i);            }        });        //奇数        Thread t2 = new Thread(()->{            for(int i = 1;i < 100;i += 2){                System.out.println("t2:" + i);            }        });        System.out.println("主线程开始");        t1.start();        t2.start();        try {            t1.join();            t2.join();        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("主线程完结");    }}

线程同步机制

1.同步代码块实现线程同步形式一

  • synchronized (dm)
/** * @Author 振帅 * @Date 2021/05/26 22:39 * synchronized 模仿取钱 */public class AccountRunnableTest implements Runnable{    class Demo { }    //锁    Demo dm = new Demo();    //账户余额    private int balance;    public AccountRunnableTest(int balance) {        this.balance = balance;    }    public int getBalance() {        return balance;    }    public void setBalance(int balance) {        this.balance = balance;    }    @Override    public void run() {        System.out.println("线程" + Thread.currentThread().getName() + "已启动...");        //synchronized (new Demo()){ //锁不住        synchronized (dm){            //1.模仿从后盾查问余额            int temp  = getBalance();            //2.模仿取款200            if (temp > 200) {                System.out.println("正在出钞,请稍后...");                temp -= 200;                try {                    Thread.sleep(5000);                } catch (InterruptedException e) {                    e.printStackTrace();                }                System.out.println("请取走你的钞票!");            } else {                System.out.println("余额有余");            }            //3.更新余额            setBalance(temp);        }    }    public static void main(String[] args) {        AccountRunnableTest account = new AccountRunnableTest(1000);        Thread t1 = new Thread(account);        Thread t2 = new Thread(account);        t1.start();        t2.start();        System.out.println("主线程开始期待...");        try {            t1.join();            t2.join();        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("最终账户余额为:"+ account.getBalance());    }}

2.同步代码块实现线程同步形式二

  • static 润饰锁
/** * @Author 振帅 * @Date 2021/05/26 22:39 * synchronized 模仿取钱 */public class AccountThreadTest extends Thread{    static class Demo { }    //锁 属于类层级 所有对象共享一个    private static Demo  dm = new Demo();    //账户余额    private int balance;    public AccountThreadTest(int balance) {        this.balance = balance;    }    public int getBalance() {        return balance;    }    public void setBalance(int balance) {        this.balance = balance;    }    @Override    public void run() {        System.out.println("线程" + Thread.currentThread().getName() + "已启动...");        synchronized (dm){            //1.模仿从后盾查问余额            int temp  = getBalance();            //2.模仿取款200            if (temp > 200) {                System.out.println("正在出钞,请稍后...");                temp -= 200;                try {                    Thread.sleep(5000);                } catch (InterruptedException e) {                    e.printStackTrace();                }                System.out.println("请取走你的钞票!");            } else {                System.out.println("余额有余");            }            //3.更新余额            setBalance(temp);        }    }    public static void main(String[] args) {        AccountThreadTest at1 = new AccountThreadTest(1000);        AccountThreadTest at2 = new AccountThreadTest(1000);        at1.start();        at2.start();        System.out.println("主线程开始期待...");        try {            at1.join();            at2.join();        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("at1账户余额为:"+ at1.getBalance());        System.out.println("at2账户余额为:"+ at2.getBalance());    }}

3.同步办法块实现线程同步形式一

  • 应用synchronized锁住整个办法
/** * @Author 振帅 * @Date 2021/05/26 22:39 * synchronized 模仿取钱 */public class AccountRunnableTest implements Runnable{    //账户余额    private int balance;    public AccountRunnableTest(int balance) {        this.balance = balance;    }    public int getBalance() {        return balance;    }    public void setBalance(int balance) {        this.balance = balance;    }    @Override    public synchronized void run() {        System.out.println("线程" + Thread.currentThread().getName() + "已启动...");        //1.模仿从后盾查问余额        int temp  = getBalance();        //2.模仿取款200        if (temp > 200) {            System.out.println("正在出钞,请稍后...");            temp -= 200;            try {                Thread.sleep(3000);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println("请取走你的钞票!");        } else {            System.out.println("余额有余");        }        //3.更新余额        setBalance(temp);    }    public static void main(String[] args) {        AccountRunnableTest account = new AccountRunnableTest(1000);        Thread t1 = new Thread(account);        Thread t2 = new Thread(account);        t1.start();        t2.start();        System.out.println("主线程开始期待...");        try {            t1.join();            t2.join();        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("最终账户余额为:"+ account                .getBalance());    }}

该形式等价于:

synchronized(this) { 整个办法体的代码 }

this 代表调用run办法的对象,由源码可知 调用run办法的对象是account

因而 synchronized(this){} 能够锁住

@Overridepublic void run() {    synchronized (this){        System.out.println("线程" + Thread.currentThread().getName() + "已启动...");        //1.模仿从后盾查问余额        int temp  = getBalance();        //2.模仿取款200        if (temp > 200) {            System.out.println("正在出钞,请稍后...");            temp -= 200;            try {                Thread.sleep(5000);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println("请取走你的钞票!");        } else {            System.out.println("余额有余");        }        //3.更新余额        setBalance(temp);    }}

4.同步办法块实现线程同步形式二

  • 当咱们对一个静态方法加锁,如:
    public synchronized static void xxx(){….}
  • 那么该办法锁的对象是类对象。每个类都有惟一的一个类对象。获取类对象的形式:类名.class。
  • 静态方法与非静态方法同时应用了synchronized后它们之间是非互斥关系的。
  • 起因在于:静态方法锁的是类对象而非静态方法锁的是以后办法所属对象。
/** * @Author 振帅 * @Date 2021/05/26 22:39 * synchronized */public class AccountThreadTest extends Thread{    //账户余额    private int balance;    public AccountThreadTest(int balance) {        this.balance = balance;    }    public int getBalance() {        return balance;    }    public void setBalance(int balance) {        this.balance = balance;    }    public synchronized static void test(){        System.out.println("线程" + Thread.currentThread().getName() + "已启动...");        System.out.println("正在出钞,请稍后...");        try {            Thread.sleep(5000);        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("请取走你的钞票!");    }    @Override    public void run() {        test();    }    public static void main(String[] args) {        AccountThreadTest at1 = new AccountThreadTest(1000);        AccountThreadTest at2 = new AccountThreadTest(1000);        at1.start();        at2.start();        System.out.println("主线程开始期待...");        try {            at1.join();            at2.join();        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("at1账户余额为:"+ at1.getBalance());        System.out.println("at2账户余额为:"+ at2.getBalance());    }}

等价于

public static void test(){    synchronized(AccountThreadTest.class){        System.out.println("线程" + Thread.currentThread().getName() + "已启动...");        System.out.println("正在出钞,请稍后...");        try {            Thread.sleep(5000);        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("请取走你的钞票!");    }}

5.应用Lock(锁)实现线程同步

  • 从Java5开始提供了更弱小的线程同步机制—应用显式定义的同步锁对象来实现。
  • java.util.concurrent.locks.Lock接口是管制多个线程对共享资源进行拜访的工具。
  • 该接口的次要实现类是ReentrantLock类,该类领有与synchronized雷同的并发性,在当前的线程安全控制中,常常应用ReentrantLock类显式加锁和开释锁。

与synchronized形式的比拟

  • Lock是显式锁,须要手动实现开启和敞开操作,而synchronized是隐式锁,执行锁定代码后主动
    开释。
  • Lock只有同步代码块形式的锁,而synchronized有同步代码块形式和同步办法两种锁。
  • 应用Lock锁形式时,Java虚拟机将破费较少的工夫来调度线程,因而性能更好。
/** * @Author 振帅 * @Date 2021/05/26 22:39 * ReentrantLock 模仿取钱 */public class AccountRunnableTest implements Runnable{    //账户余额    private int balance;    //筹备锁    private ReentrantLock lock = new ReentrantLock();    public AccountRunnableTest(int balance) {        this.balance = balance;    }    public int getBalance() {        return balance;    }    public void setBalance(int balance) {        this.balance = balance;    }    @Override    public void run() {        //开始加锁        lock.lock();        System.out.println("线程" + Thread.currentThread().getName() + "已启动...");        //1.模仿从后盾查问余额        int temp  = getBalance();        //2.模仿取款200        if (temp > 200) {            System.out.println("正在出钞,请稍后...");            temp -= 200;            try {                Thread.sleep(3000);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println("请取走你的钞票!");        } else {            System.out.println("余额有余");        }        //3.更新余额        setBalance(temp);        //解锁        lock.unlock();    }    public static void main(String[] args) {        AccountRunnableTest account = new AccountRunnableTest(1000);        Thread t1 = new Thread(account);        Thread t2 = new Thread(account);        t1.start();        t2.start();        System.out.println("主线程开始期待...");        try {            t1.join();            t2.join();        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("最终账户余额为:"+ account.getBalance());    }}

线程通信

1.Object类罕用的办法

办法申明性能介绍
void wait()用于使得线程进入期待状态,直到其它线程调用notify()或notifyAll()方 法
void wait(long timeout)用于进入期待状态,直到其它线程调用办法或参数指定的毫秒数曾经过来为止
void notify()用于唤醒期待的单个线程
void notifyAll()用于唤醒期待的所有线程
/** * @Author 振帅 * @Date 2021/05/26 23:53 * 线程通信 两个线程交替打印1-100 */public class ThreadCommunicateTest implements Runnable {    private int cnt = 1;    @Override    public void run() {        while (true) {            synchronized (this){                //用于唤醒期待的单个线程 写在锁外面                notify();                if(cnt <= 100){                    System.out.println("线程:"+ Thread.currentThread().getName() +"中的cnt:= " +cnt);                    try {                        Thread.sleep(200);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                    cnt++;                    try {                        //用于使得线程进入期待状态,直到其它线程调用notify()或notifyAll()办法 写在锁外面                        //以后线程打印完一个数 为了避免持续打印 调用wait()                        wait();                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }else {                    break;                }            }        }    }    public static void main(String[] args) {        ThreadCommunicateTest tc = new ThreadCommunicateTest();        Thread t1 = new Thread(tc);        Thread t2 = new Thread(tc);        t1.start();        t2.start();    }}

2.生产者消费者模型实现

仓库类

/** * @Author 振帅 * @Date 2021/05/27 0:20 * 仓库类 */public class StoreHouse {    //记录产品的数量    private int cnt = 0;        //生产办法    public synchronized void produceProduct(){        notify();        if (cnt < 10) {            System.out.println("线程"+Thread.currentThread().getName()+"正在生产第"+(cnt+1)+"个产品");            cnt++;        } else {            try {                wait();            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }         //生产办法    public synchronized void consumerProduct(){        notify();        if (cnt > 0) {            System.out.println("线程"+Thread.currentThread().getName()+"正在生产第"+(cnt)+"个产品");            cnt--;        } else {            try {                wait();            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}

生产者

/** * @Author 振帅 * @Date 2021/05/27 0:22 * 生产者 */public class ProduceThread extends Thread{    //申明一个仓库类型的援用作为成员变量,为了能调用仓库类中的生产办法 合成复用准则    private StoreHouse storeHouse;    //为了确保两个线程共用一个仓库    public ProduceThread(StoreHouse storeHouse){        this.storeHouse = storeHouse;    }    @Override    public void run() {        while (true) {            storeHouse.produceProduct();            try {                Thread.sleep(500);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}

消费者

/** * @Author 振帅 * @Date 2021/05/27 0:22 * 消费者 */public class ConsumerThread extends Thread{    //申明一个仓库类型的援用作为成员变量,为了能调用仓库类中的生产办法 合成复用准则    private StoreHouse storeHouse;    //为了确保两个线程共用一个仓库    public ConsumerThread(StoreHouse storeHouse){        this.storeHouse = storeHouse;    }    @Override    public void run() {        while (true) {            storeHouse.consumerProduct();            try {                Thread.sleep(1000);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}

测试类

/** * @Author 振帅 * @Date 2021/05/27 0:27 */public class StoreHouseTest {    public static void main(String[] args) {        //创立仓库类对象        StoreHouse storeHouse = new StoreHouse();        ProduceThread t1 = new ProduceThread(storeHouse);        ConsumerThread t2 = new ConsumerThread(storeHouse);        t1.start();        t2.start();    }}

创立和启动线程的形式三

  • 实现Callable接口
  • FutureTask类 extends RunnableFuture extends Runnable
/** * @Author 振帅 * @Date 2021/05/27 0:44 */public class ThreadCallableTest implements Callable<Integer> {    @Override    public Integer call() throws Exception {        //计算1-10000之间累加和        int sum = 0;        for (int i = 1;i <= 1000; i++){            sum = sum+i;        }        System.out.println("计算的后果为:" + sum);        return sum;    }    public static void main(String[] args) {        ThreadCallableTest tct = new ThreadCallableTest();        //用于形容可勾销的异步计算,该类提供了Future接口的根本实        //现,包含启动和勾销计算、查问计算是否实现以及检索计算结果的办法,也能够用于获取办法调用        //后的返回后果        FutureTask<Integer> task = new FutureTask<Integer>(tct);        Thread th = new Thread(task);        th.start();        Integer result = null;        try {            //获取call办法计算的后果            result = task.get();        } catch (InterruptedException e) {            e.printStackTrace();        } catch (ExecutionException e) {            e.printStackTrace();        }        System.out.println("线程处理结果:" + result);    }}

创立和启动线程的形式四

  • Executors类

工具类和线程池的工厂类,能够创立并返回不同类型的线程池,罕用办法如下:

办法申明性能介绍
static ExecutorService newCachedThreadPool()创立一个可依据须要创立新线程的线程池
static ExecutorService newFixedThreadPool(int nThreads)创立一个可重用固定线程数的线程池
static ExecutorService newSingleThreadExecutor()创立一个只有一个线程的线程池
  • ExecutorService接口

真正的线程池接口,次要实现类是ThreadPoolExecutor,罕用办法如下:

办法申明性能介绍
void execute(Runnable command)执行工作和命令,通常用于执行Runnable
Future submit(Callable task)执行工作和命令,通常用于执行Callable
void shutdown()启动有序敞开
public class ThreadPoolTest {    public static void main(String[] args) {        ExecutorService executorService = Executors.newFixedThreadPool(10);        ThreadCallableTest threadCallableTest = new ThreadCallableTest();        Future<Integer> future = executorService.submit(threadCallableTest);        Integer result = null;        try {            result = future.get();        } catch (InterruptedException e) {            e.printStackTrace();        } catch (ExecutionException e) {            e.printStackTrace();        }        System.out.println("线程处理结果:" + result);        executorService.shutdown();    }}