Browse Source

1116 thread

Demi 6 months ago
parent
commit
07654ecebc

+ 14 - 0
lesson/src/com/sf/thread_new/Main.java

@@ -0,0 +1,14 @@
+package com.sf.thread_new;
+
+import java.util.Scanner;
+
+public class Main {
+
+    public static void main(String[] args) {
+        System.out.println("Hello World");
+
+        Scanner scanner = new Scanner(System.in);
+        String line = scanner.nextLine();
+        System.out.println(line);
+    }
+}

+ 12 - 0
lesson/src/com/sf/thread_new/MyRejected.java

@@ -0,0 +1,12 @@
+package com.sf.thread_new;
+
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.ThreadPoolExecutor;
+
+public class MyRejected implements RejectedExecutionHandler {
+
+    @Override
+    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
+        System.out.println("MyRejected");
+    }
+}

+ 30 - 0
lesson/src/com/sf/thread_new/TestCallable.java

@@ -0,0 +1,30 @@
+package com.sf.thread_new;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.FutureTask;
+
+// Callable需要指定接收结果的数据类型
+public class TestCallable implements Callable<String> {
+
+    // 不是run 是call
+    // 而且有了抛出异常的处理
+    @Override
+    public String call() throws Exception {
+        System.out.println(Thread.currentThread().getName() + " is running");
+        return "hello callable";
+    }
+
+    public static void main(String[] args) throws Exception{
+        // 快递
+        TestCallable tc = new TestCallable();
+        // 接收快递单
+        FutureTask<String> task = new FutureTask<>(tc);
+        // 执行时 也是通过快递单
+        Thread thread1 = new Thread(task,"thread1");
+        thread1.start();
+
+        // 接收结果
+        String result = task.get();
+        System.out.println(result);
+    }
+}

+ 73 - 0
lesson/src/com/sf/thread_new/TestCreatedPool.java

@@ -0,0 +1,73 @@
+package com.sf.thread_new;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+public class TestCreatedPool {
+
+    public static void main(String[] args) {
+//        Arrays
+//        Collections
+        // .var
+        // 通过 Executors 线程池工具类 来创建 提供好的线程池
+        // 接收一个任务 如果没有空闲线程 就创建一个线程
+        ExecutorService threadPool = Executors.newCachedThreadPool();
+        // 同一时间使用的线程数 是10个
+        ExecutorService threadPool1 = Executors.newFixedThreadPool(10);
+
+//        for (int i = 0; i < 100; i++) {
+//            threadPool1.execute(new Runnable() {
+//                @Override
+//                public void run() {
+//                    try {
+//                        Thread.sleep(2000);
+//                    } catch (InterruptedException e) {
+//                        throw new RuntimeException(e);
+//                    }
+//                    System.out.println(Thread.currentThread().getName() + " run");
+//                }
+//            });
+//        }
+
+        // 支持调度的线程池
+        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
+//        scheduledThreadPool.schedule(new Runnable() {
+//            @Override
+//            public void run() {
+//                System.out.println("newScheduledThreadPool");
+//            }
+//        },3, TimeUnit.SECONDS);
+//        // 延时3s执行
+
+//        scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
+//            @Override
+//            public void run() {
+//                System.out.println("newScheduledThreadPool");
+//            }
+//        },1,3,TimeUnit.SECONDS);
+        // initialDelay 初始延迟时间
+        // period 周期
+        // unit 时间单位
+        // 这里的意思是 1s后每3s执行一次
+
+        // 单个的线程
+        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
+        for (int i = 0; i < 10; i++) {
+            singleThreadExecutor.execute(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        Thread.sleep(1000);
+                    } catch (InterruptedException e) {
+                        throw new RuntimeException(e);
+                    }
+                    System.out.println(Thread.currentThread().getName() + " run");
+                }
+            });
+        }
+    }
+}

+ 23 - 0
lesson/src/com/sf/thread_new/TestRunnable.java

@@ -0,0 +1,23 @@
+package com.sf.thread_new;
+
+// 使用更加广泛
+// 快捷键 alt+enter
+public class TestRunnable implements Runnable{
+
+    @Override
+    public void run() {
+        // 如果要打印当前线程的名字
+        System.out.println(Thread.currentThread().getName() + " is running");
+    }
+
+    public static void main(String[] args) {
+        // 提供的是线程的执行逻辑
+        Runnable runnable = new TestRunnable();
+        // 将Runnable实现好的运行逻辑 给到Thread 也就是使用对应的有参构造器
+        Thread thread1 = new Thread(runnable);
+        thread1.start();
+
+        Thread thread2 = new Thread(runnable,"thread2");
+        thread2.start();
+    }
+}

+ 29 - 0
lesson/src/com/sf/thread_new/TestThread.java

@@ -0,0 +1,29 @@
+package com.sf.thread_new;
+
+public class TestThread extends Thread{
+
+    public TestThread(){}
+    public TestThread(String name){
+        // 名字是父类提供的属性
+        // Thread(name) 是父类提供的构造器
+        super(name);
+    }
+
+    @Override
+    public void run() {
+        // Thread-0 Thread-1
+        System.out.println(getName() + " is running");
+    }
+
+    public static void main(String[] args) {
+        // main
+        System.out.println(Thread.currentThread().getName() + " is running");
+        // 创建我们定义的类的线程
+        TestThread thread1 = new TestThread();
+        // 直接调用run方法相当于调用函数 不能触发多线程的执行
+        thread1.start();
+
+        TestThread thread2 = new TestThread("thread2");
+        thread2.start();
+    }
+}

+ 62 - 0
lesson/src/com/sf/thread_new/TestThreadPool.java

@@ -0,0 +1,62 @@
+package com.sf.thread_new;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+public class TestThreadPool {
+
+    public static void main(String[] args) {
+        // 创建线程池
+        // CallerRunsPolicy 这里是ThreadPoolExecutor的静态内部类
+        ThreadPoolExecutor executor = new ThreadPoolExecutor(
+                5,10,200, TimeUnit.MILLISECONDS,
+                new ArrayBlockingQueue<>(5), new MyRejected()
+        );
+        // 核心参数
+        // corePoolSize  核心池的大小 指的是核心线程的数量
+        // maximumPoolSize 线程池的最大线程数  核心线程数 + 非核心线程数
+        // keepAliveTime  保持存活时间  非核心线程空闲时的存活时间
+        // unit 时间单位 天/小时/分钟等  这里是当非核心线程空闲了200ms 那么就销毁
+        // workQueue 阻塞队列
+        //   刚开始线程池是没有线程的 有任务需要线程时才创建 直到创建到第五个 核心线程(正式工)创建完毕
+        //     此时每个核心线程都在执行任务 有新的任务到达时 放在阻塞队列中排队 这里是最多排5个
+        //     当核心线程都在占用 队列也满了 此时创建非核心线程(临时工)5个
+        //     如果到达最大线程数 同时没有任何空闲线程和队列空间 那么拒绝任务
+
+        // 使用线程池 执行任务
+        // 核心 0 1 2 3 4
+        // 队列 5 6 7 8 9
+        // 非核心 10 11 12 13 14
+        for (int i = 0; i < 16; i++) {
+            MyTask task = new MyTask(i);
+            // 将任务提交到线程池中
+            executor.execute(task);
+            // 打印线程池中参数的变化
+            System.out.println("线程池中线程数目:" + executor.getPoolSize());
+            System.out.println("线程池中队列等待的数目:" + executor.getQueue().size());
+        }
+    }
+}
+
+class MyTask implements Runnable {
+
+    private int taskNum;
+
+    public MyTask(int taskNum) {
+        this.taskNum = taskNum;
+    }
+
+    @Override
+    public void run() {
+        System.out.println(Thread.currentThread().getName() + " run " + taskNum);
+        // 每个任务都有一定的执行时间
+        // 让线程睡一会儿 4000ms = 4s
+        try {
+            Thread.currentThread().sleep(4000);
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        }
+        System.out.println(Thread.currentThread().getName() + " run " + taskNum + " done");
+    }
+}

+ 23 - 0
lesson/src/com/sf/thread_new/TestTimer.java

@@ -0,0 +1,23 @@
+package com.sf.thread_new;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+public class TestTimer {
+
+    public static void main(String[] args) {
+        // 计时器类
+        Timer timer = new Timer();
+        // 调用一个调度方法 接收一个计时器任务
+        // class TimerTask implements Runnable
+        timer.schedule(new TimerTask() {
+            @Override
+            public void run() {
+                System.out.println("Task Run");
+            }
+        }, 0, 1000);
+        // delay 延迟时间
+        // period 间隔时间  单位是ms 1000ms = 1s
+        // 适用于 每隔一段时间 执行一个任务
+    }
+}

+ 114 - 0
lesson/src/com/sf/thread_new/bank/DrawThread.java

@@ -0,0 +1,114 @@
+package com.sf.thread_new.bank;
+
+// 银行取钱窗口
+// 模拟多人在不同窗口取钱的场景
+public class DrawThread extends Thread {
+
+    // 操作的账户
+    private Account account;
+    // 取款金额
+    private double drawAmount;
+
+    // 创建构造器 同时调用父类的构造器
+    public DrawThread(String name, Account account, double drawAmount) {
+        super(name);
+        this.account = account;
+        this.drawAmount = drawAmount;
+    }
+
+    @Override
+    public void run() {
+        // 取钱操作
+        account.handle(drawAmount);
+//        handle2(account,drawAmount);
+    }
+
+    public synchronized void handle(){}
+    public void handle1(){
+        // 如果synchronized 修饰的是非静态方法  锁住的是当前对象 this = new DrawThread()
+        synchronized (this){}
+    }
+    public synchronized static void handle2(Account account, double drawAmount){
+//        if (account.getBalance() >= drawAmount) {
+//            try {
+//                Thread.sleep(200);
+//            } catch (InterruptedException e) {
+//                throw new RuntimeException(e);
+//            }
+//
+//            account.setBalance(account.getBalance() - drawAmount);
+//            System.out.println(Thread.currentThread().getName() + "取钱成功,余额为:" + account.getBalance());
+//        } else {
+//            System.out.println(Thread.currentThread().getName()  + "余额不足");
+//        }
+    }
+    public void handle3(){
+        // 如果synchronized 修饰的是静态方法  锁住的是类对象
+        synchronized (DrawThread.class){}
+    }
+
+    public static void main(String[] args) {
+        Account account = new Account("001", 1000);
+//        new DrawThread("zhangsan", account, 600).start();
+
+        // 构造多人 触发余额为负数的情况
+        // 出现原因是:多个线程都对账户的余额进行扣减
+        for (int i = 0; i < 10; i++) {
+            new DrawThread(i + "", account, 600).start();
+        }
+    }
+}
+
+class Account {
+    private String accountNo;
+    private double balance;
+
+    public Account() {
+    }
+
+    public Account(String accountNo, double balance) {
+        this.accountNo = accountNo;
+        this.balance = balance;
+    }
+
+    // 使用synchronized来修饰方法 代表方法被加了锁
+    // 只有一个线程能获取锁 然后执行方法 其他线程此时要等待
+    // 当此线程执行完 释放锁 其他等待的线程再争抢锁
+    // 如果在方法上加锁 代表是 以当前对象作为锁 来被争抢
+
+    // 把取钱逻辑从窗口 挪到账户中
+    // 此时先判断 账户是否被其他线程获取 如果是 等待 如果不是 那么获取账户锁
+    public synchronized void handle(double drawAmount){
+        if (this.balance >= drawAmount) {
+            try {
+                Thread.sleep(200);
+            } catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+
+            this.balance = balance - drawAmount;
+            System.out.println(Thread.currentThread().getName() + "取钱成功,余额为:" + balance);
+        } else {
+            System.out.println(Thread.currentThread().getName()  + "余额不足");
+        }
+
+//        synchronized (this) {}
+    }
+
+
+    public String getAccountNo() {
+        return accountNo;
+    }
+
+    public void setAccountNo(String accountNo) {
+        this.accountNo = accountNo;
+    }
+
+    public double getBalance() {
+        return balance;
+    }
+
+    public void setBalance(double balance) {
+        this.balance = balance;
+    }
+}

+ 17 - 0
lesson/src/com/sf/thread_new/bank/TestSynchronized.java

@@ -0,0 +1,17 @@
+package com.sf.thread_new.bank;
+
+public class TestSynchronized {
+
+    // .java源文件 -> .class字节码文件 -> jvm识别为机器语言
+    // 同步方法
+    public synchronized void method(){
+        System.out.println("synchronized method");
+    }
+
+    public void method1(){
+        // 同步代码块 使用当前对象作为锁
+        synchronized(this) {
+            System.out.println("synchronized method1");
+        }
+    }
+}

+ 29 - 0
lesson/src/com/sf/thread_new/jvm/TestFrames.java

@@ -0,0 +1,29 @@
+package com.sf.thread_new.jvm;
+
+public class TestFrames {
+
+    public static void main(String[] args) {
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                method1();
+            }
+        }).start();
+
+        method1();
+        System.out.println("main");
+    }
+
+    private static void method1(){
+        String res = method2();
+        // 局部变量
+        int i = 10;
+        System.out.println("method1");
+    }
+
+    private static String method2(){
+        System.out.println("method2");
+        String str = new String("hello");
+        return str;
+    }
+}