线程基础

  • 一个进程可以有多个线程。
  • 进程是资源分配的单位

测试

测试0-callable的使用

public class T {
    public static void main(String[] args) throws Exception {
        /*//连接池调用Callable
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        Future<Boolean> future = executorService.submit(new CallableTest());
        System.out.println(future.get());
        executorService.shutdown();*/

        FutureTask<Boolean> futureTask = new FutureTask<Boolean>(new CallableTest());
        new Thread(futureTask,"A").start();
        new Thread(futureTask,"B").start();//测试Callable缓存:调用两次futureTask,观察输出几个“call”
        System.out.println(futureTask.get());//阻塞一分钟后,返回结果

    }
}

class CallableTest implements Callable<Boolean> {
    @Override
    public Boolean call() throws Exception {
        System.out.println("call");
        TimeUnit.MINUTES.sleep(1);//阻塞一分钟后,返回结果
        return true;
    }
}

 

 

 

 细节:

  • 有缓存
  • 返回结果可能会等待,会阻塞。可以使用异步通信来处理

测试1-线程常用方法

线程状态

 

 

public class StateThreadTest  {
    public static void main(String[] args) throws InterruptedException{
        Thread thread = new Thread(()->{
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("子线程结束了");
        });
        Thread.State state = thread.getState();
        System.out.println("【新建状态】"+state);//new

        thread.start();
        state = thread.getState();
        System.out.println("【就绪状态】"+state);//runnable

        while (state != Thread.State.TERMINATED){
            Thread.sleep(1000);
            state = thread.getState();
            System.out.println("【非终止状态】"+state);
        }
    }
}

 

sleep()

  sleep()让调用线程进入睡眠状态,让出执行机会给其他线程,等到休眠时间结束后,线程进入就绪状态和其他线程一起竞争cpu的执行时间。
       因为sleep() 是static静态的方法,他不能改变对象的机锁,当一个synchronized块中调用了sleep() 方法,线程虽然进入休眠,但是对象的机锁没有被释放,其他线程依然无法访问这个对象。

  因为一个类中的静态资源在类class被java虚拟机加载时就已经被初始化了,而非静态资源要在对象实例化的时候才会被初始化。sleep()方法是静态的,只依赖于类,不依赖于对象,而锁是对象锁,所以不能改变锁

  sleep模拟网络延时,倒计时。

public class SleepThreadTest {
    public static void main(String[] args) throws InterruptedException {
//        timedown();
        Date startDate = new Date(System.currentTimeMillis());
        while (true){
            Thread.sleep(1000);
            System.out.println(new SimpleDateFormat("HH:mm:ss").format(startDate));
            startDate = new Date(System.currentTimeMillis());//更新时间
        }
    }

    /**
     * 模拟倒计时
     * @throws InterruptedException
     */
    static void timedown() throws InterruptedException {
        int num = 10;
        while (true){
            Thread.sleep(1000);
            System.out.println(num--);
            if(num<=0)
                break;
        }
    }
}

sleep() VS wait()

  1. 释放锁:wait 可以释放当前线程对 lock 对象锁的持有,而 sleep 则不会
  2. 使用场景:sleep 一般用于当前线程休眠,或者轮循暂停操作,wait 则多用于多线程之间的通信。
  3. 所属类:sleep 是 Thread 类的静态本地方法,wait 则是 Object 类的本地方法
  4. 使用限制:使用 sleep 方法可以让让当前线程休眠,时间一到当前线程继续往下执行,在任何地方都能使用。而使用 wait 方法则必须放在 synchronized 块里面。wait 还需要额外的方法 notify/ notifyAll 进行唤醒,它们同样需要放在 synchronized 块里面,且获取对象的锁。
  5. 线程切换:sleep 会让出 CPU 执行时间且强制上下文切换,而 wait 则不一定,wait 后可能还是有机会重新竞争到锁继续执行的。
public class SleepThreadTest {
    public static void main(String[] args) {
        Sleep sleep = new Sleep();
        Thread sleepThread = new Thread(new Runnable() {
            @Override
            public void run() {
                sleep.sleep();
            }
        });
        sleepThread.start();

        Thread waitThread = new Thread(new Runnable() {
            @Override
            public void run() {
                sleep.mWait();
            }
        });
        waitThread.start();

    }
}

class Sleep{
    public void sleep(){
        synchronized(this){
            try{
                System.out.println(" Sleep 。当前时间:"+System.currentTimeMillis());
                Thread.sleep(5*1000);
            }
            catch(Exception e){
                System.out.println(e);
            }
        }
    }
    public void mWait(){
        synchronized(this){
            System.out.println(" Wait 。结束时间:"+System.currentTimeMillis());
        }
    }
}

 

 

 

 

public class WaitThreadTest {
    public static void main(String[] args) {
        Wait wait = new Wait();
        Thread waitThread = new Thread(new Runnable() {
            @Override
            public void run() {
                wait.mWait();
            }
        });
        waitThread.start();

        Thread sleepThread = new Thread(new Runnable() {
            @Override
            public void run() {
                wait.mSleep();
            }
        });
        sleepThread.start();
    }
}
class Wait {
    public void mSleep() {
        try {
            Thread.sleep(3 * 1000);
        } catch (Exception e) {
            System.out.println(e);
        }
        synchronized (this) {
            this.notifyAll();
            System.out.println(" 唤醒等待 。 结束时间:" + System.currentTimeMillis());
        }
    }
    public void mWait() {
        synchronized (this) {
            try {
                System.out.println(" 等待开始 。 当前时间:" + System.currentTimeMillis());
                this.wait();
            } catch (Exception e) {
                System.out.println(e);
            }
        }
    }
}

 

 

 

线程的优先级

public class PriorityThreadTest {
    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName()+"----"+Thread.currentThread().getPriority());
        MyPriority myPriority = new MyPriority();

        Thread t1 = new Thread(myPriority,"thread1");
        Thread t2 = new Thread(myPriority,"thread2");
        Thread t3 = new Thread(myPriority,"thread3");
        Thread t4 = new Thread(myPriority,"thread4");
        Thread t5= new Thread(myPriority,"thread5");

        t1.setPriority(8);
        t1.start();

        t2.setPriority(4);
        t2.start();

        t3.setPriority(Thread.NORM_PRIORITY);
        t3.start();

        t4.setPriority(Thread.MAX_PRIORITY);
        t4.start();

        t5.setPriority(Thread.MIN_PRIORITY);
        t5.start();
    }
}
class MyPriority implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"----"+Thread.currentThread().getPriority());
    }
}

join()插队

  • 等待插队线程结束后,再执行其他线程。
  • 可以想象成插队
public class JoinThreadTest_ChaDui implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 10 ; i++) {
            try {
                Thread.sleep(1000);
                System.out.println("------插队线程------"+i);
            } catch (InterruptedException e) {
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        JoinThreadTest_ChaDui joinThreadTest_chaDui = new JoinThreadTest_ChaDui();
        Thread chaduiThread = new Thread(joinThreadTest_chaDui);
        chaduiThread.start();

        for (int i = 0; i < 20 ; i++) {
            System.out.println("主线程"+i);
            if(i==3){
                chaduiThread.join();
            }
        }
    }
}

 

 stop()

  • 推荐使用标志位
  • 利用次数,不建议死循环
  • jdk过时方法,不建议
public class StopThreadTest_UseFlag implements Runnable{
    private boolean flag = true;
    @Override
    public void run() {
        int i=0;
        while (flag){
            System.out.println("-------子线程运行----------"+i++);
        }
    }
    public boolean stop(){
        this.flag = false;
        return flag;
    }
    public static void main(String[] args) {
        StopThreadTest_UseFlag sttu = new StopThreadTest_UseFlag();
        new Thread(sttu).start();;

        for (int i = 0; i < 10; i++) {
            System.out.println("main线程运行"+i);
            if(i==4){
                sttu.stop();
            }
        }
    }
}

 守护线程

  • 虚拟机不用等待守护线程执行完毕
  • 虚拟机必须确保用户线程执行完毕
  • 用户线程:main
  • 守护线程:gc、后台记录操作日志、监控内存
public class DaemonTest {
    public static void main(String[] args) {
        new Thread(new You()).start();

        Thread godThread = new Thread(new God());
        godThread.setDaemon(true);
        godThread.start();
    }
}
class God implements Runnable{

    @Override
    public void run() {
        while(true){
            System.out.println("上帝守护每一天");
        }
    }
}
class You implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 365; i++) {
            System.out.println("开开心心每一天"+i);
        }
    }
}

 yield()

  • 让当前正在执行的线程暂停,但不阻塞。
  • 将线程从运行状态转为就绪状态
  • 让cpu重新调度,礼让不一定成功,看cpu心情
public class YieldThreadTest {
    public static void main(String[] args) {
        YildThread yildThread = new YildThread();
        new Thread(yildThread,"礼让吗1").start();
        new Thread(yildThread,"礼让吗2").start();

    }

}
class YildThread implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"开始");
        Thread.yield();
        System.out.println(Thread.currentThread().getName()+"结束");
    }
}

 

 

 测试...

模拟龟兔赛跑

/**
 * 模拟龟兔赛跑
 */
public class RaceTest implements Runnable {
    private static String winner;//共享变量
    @Override
    public void run() {
        for (int i = 0; i <= 1000 ; i++) {
            if(Thread.currentThread().getName().equals("兔子") && i/20==0){//模拟兔子睡了
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            boolean winflag = gameOver(i);
            if(winflag){
                break;
            }
            System.out.println(Thread.currentThread().getName()+"跑了"+i+"步");

        }
    }

    /**
     * 是否跑到了终点
     */
    public boolean gameOver(int steps){
        if(winner !=null){
            return true;
        }
        if(steps == 1000){
            winner = Thread.currentThread().getName();
            System.out.println("************************赢家是"+winner);
        }
        return false;
    }

    public static void main(String[] args) {
        RaceTest raceTest = new RaceTest();
        new Thread(raceTest,"兔子").start();
        new Thread(raceTest,"tortoise").start();

    }
}

 

下载网络图片

package com.fh.thread.base.createThread;

import org.apache.commons.io.FileUtils;

import java.io.*;
import java.net.URL;
import java.util.concurrent.*;

public class CallableTest_DownloadPic implements Callable<Boolean> {
    String url;
    String name;
    public CallableTest_DownloadPic(String url,String name) {
        this.url = url;
        this.name = name;
    }

    @Override
    public Boolean call() throws Exception {
        DownloadPic downloadPic = new DownloadPic();
        downloadPic.download(url,name);
        System.out.println("下载了文件:"+name);
        return true;
    }

    class DownloadPic{
        void download(String url,String name){
            try {
                FileUtils.copyURLToFile(new URL(url),new File(name));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CallableTest_DownloadPic cdp1 = new CallableTest_DownloadPic("https://img0.baidu.com/it/u=3212253201,1261694971&fm=253&fmt=auto&app=120&f=PNG?w=488&h=594","src/main/resources/pic/1.png");
        CallableTest_DownloadPic cdp2 = new CallableTest_DownloadPic("https://img0.baidu.com/it/u=3538204079,1027715215&fm=253&fmt=auto&app=138&f=PNG?w=500&h=249","src/main/resources/pic/2.png");
        CallableTest_DownloadPic cdp3 = new CallableTest_DownloadPic("https://img2.baidu.com/it/u=1656231567,3874501242&fm=253&fmt=auto&app=120&f=JPEG?w=900&h=426","src/main/resources/pic/3.png");
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        Future<Boolean> future1 = executorService.submit(cdp1);
        Future<Boolean> future2 = executorService.submit(cdp2);
        Future<Boolean> future3 = executorService.submit(cdp3);
        boolean result1 = future1.get();
        boolean result2 = future1.get();
        boolean result3 = future1.get();
        System.out.println(result1+"---"+result2+"---"+result3);
        executorService.shutdown();
        
    }
}

模拟买卖票

public class TicketTest {
    public static void main(String[] args) {
        Ticket ticket = new Ticket();
//        1.
//        new Thread(()->{
//            ticket.sellTicket();
//        },"小明").start();
//        new Thread(()->{
//            ticket.sellTicket();
//        },"花花").start();
//        new Thread(()->{
//            ticket.sellTicket();
//        },"JAY").start();

        new Thread(() -> {
            for (int i = 0; i < 60; i++) {
                ticket.sellTicket();
            }
        }, "窗口1").start();
        new Thread(() -> {
            for (int i = 0; i < 60; i++) {
                ticket.sellTicket();
            }
        }, "窗口2").start();
        new Thread(() -> {
            for (int i = 0; i < 60; i++) {
                ticket.sellTicket();
            }
        }, "窗口3").start();

    }
}

class Ticket {
    int num = 10;

    public void sellTicket() {
        synchronized (this) {
            if (num > 0) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {

                }

                System.out.println(Thread.currentThread().getName() + "卖了" + num--);
            }

        }
    }
//    1、
//    public void sellTicket(){
//        while (true){
//            try {
//                Thread.sleep(1000);
//            } catch (InterruptedException e) {
//
//            }
//            synchronized (this){
//                if(num > 0){
//                    System.out.println(Thread.currentThread().getName()+num--);
//                }else break;
//            }
//
//        }
//    }
}

 

posted @ 2022-06-17 15:12  禁止摆烂  阅读(27)  评论(0)    收藏  举报