首页 > 编程语言 >Java JUC&多线程 基础完整版

Java JUC&多线程 基础完整版

时间:2024-05-24 15:09:02浏览次数:15  
标签:JUC 多线程 Thread void MyThread 线程 new 完整版 public

Java JUC&多线程 基础完整版

目录

1、 多线程的第一种启动方式之继承Thread类

优点: 比较简单,可以直接使用Thread类中的方法,缺点: 可以拓展性比较差,不能再继承其他的类

线程类MyThread

public class MyThread extends Thread {


    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName() + "Hello World");
        }
    }
}

执行类ThreadDemo

public class ThreadDemo {

    public static void main(String[] args) {
        /*
         * 多线程第一种启动方式
         * 1. 自己定义一个类继承Thread
         * 2. 重写run方法
         * 3. 创建启动对象,并启动线程
         */

        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();

        t1.setName("线程1");
        t2.setName("线程2");
        t1.start();
        t2.start();
    }

}

2、多线程的第二种启动方式之实现Runnable接口

优点: 拓展性强,实现该接口的同时可以继承其他的类,缺点: 相对复杂,不能直接使用Thread类中的方法

线程类MyRunnable

public class MyRunnable implements Runnable {

    @Override
    public void run() {
        // 线程要执行的代码
        for (int i = 0; i < 100; i++) {
            // 先获取当前线程的对象
            Thread thread = Thread.currentThread();
            System.out.println(thread.getName() + "Hello World");
        }
    }
}

执行类ThreadDemo

public class ThreadDemo {

    public static void main(String[] args) {
        /*
         * 多线程的第二种启动方式
         * 1. 自定义一个类实现Runnable接口
         * 2. 重写里面的run方法
         * 3. 创建自己的类对象
         * 4.创建一个Thread类的对象,并开启线程
         *
         */

        // 任务对象
        MyRunnable myRun = new MyRunnable();
        // 线程对象
        Thread t1 = new Thread(myRun);
        Thread t2 = new Thread(myRun);

        // 给线程设置名字
        t1.setName("线程1");
        t2.setName("线程2");
        // 开启线程
        t1.start();
        t2.start();
    }
}

3、多线程的第三种实现方式之实现Callable接口

优点: 拓展性强,实现该接口的同时可以继承其他的类,相对复杂,不能直接使用Thread类中的方法

线程类MyCallable

public class MyCallable implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        // 求1~100之间的和
        int sum = 0;
        for (int i = 0; i <= 100; i++) {
            sum = sum + i;
        }
        return sum;
    }
}

执行类ThreadDemo

public class ThreadDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        /*
         * 多线程的第三种实现方式
         *   特点: 可以获取到多线程的运行结果
         *  1. 创建一个MyCallable类实现Callable接口
         *  2. 重写call (是有返回值的,表示多线程运行的结果)
         *  3. 创建MyCallable的对象 (表示多线程要执行的任务)
         *  4. 创建FutureTask的对象 (管理多线程运行的结果)
         *  5. 创建Thread类的对象 并启动(表示线程)
         */

        // 创建MyCallable对象 (表示要执行的多线程的任务)
        MyCallable mc = new MyCallable();
        // 创建FutureTask的对象 (作用管理多线程运行的结果)
        FutureTask<Integer> ft = new FutureTask<>(mc);
        // 创建线程对象
        Thread t1 = new Thread(ft);
        // 启动线程
        t1.start();

        // 获取多线程运行的结果
        Integer result = ft.get();
        System.out.println(result);

    }
}

4、多线的常用成员方法

  • String getName() 返回此线程的名称
  • void setName(String name) 设置线程名称(构造方法也可以设置名称)
    • 细节
      • 1.如果不设置线程名称,线程也是有默认序号的,从0开始格式为Thread-X
      • 2.如果给线程设置名称可以使用setName和子类的构造方法
    • 细节
      • 当jvm虚拟机启动后会自动启动多条线程,其中就有一个线程名字为main他的作用就是调用main方法,执行里面的代码
  • static void sleep(long time) 让线程休眠指定的时间, 单位为毫秒
    • 细节
      • 哪条线程执行到了这个方法,那么哪条线程就会在这里停留相对于的时间方法的参数就表示睡眠的时间,单位为毫秒时间到了后线程会自动苏醒,并继续执行

线程类MyThread

public class MyThread extends Thread {

    // 构造方式设置线程名称
    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName() + "@" + i);
        }
    }
}

执行类ThreadDemo

public class ThreadDemo {

    public static void main(String[] args) {

        // 1.创建线程的对象
        MyThread t1 = new MyThread("飞机");
        MyThread t2 = new MyThread("坦克");


        // 2.开启线程
        t1.start();
        t2.start();

        // 哪条线程执行到这个方法,此时获取的就是哪条线程的对象
        Thread thread = Thread.currentThread();
        System.out.println("main方法线程" + thread.getName());
    }
}

5、线程的优先级

  • setPriority(int newPriority) 设置线程优先级
  • final int getPriority() 获取线程优先级

线程类MyRunnable

public class MyRunnable implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + "===" + i);
        }
    }
}

执行类ThreadDemo

public class ThreadDemo {

    public static void main(String[] args) {
        /*
         * setPriority(int newPriority)  设置线程优先级
         * final int getPriority() 获取线程优先级
         *
         */
        // 创建线程要执行的参数对象
        MyRunnable mr = new MyRunnable();
        // 创建线程对象
        Thread t1 = new Thread(mr, "飞机");
        Thread t2 = new Thread(mr, "坦克");

        // 设置优先级
        t1.setPriority(1);
        t2.setPriority(10);

        // 查看线程优先级
        System.out.println(t1.getPriority());
        System.out.println(t2.getPriority());

        // 启动线程
        t1.start();
        t2.start();
    }
}

6、守护线程

final void setDaemon(boolean on) 设置为守护线程(备胎线程),当其他的非守护线程执行结束后,守护线程会陆续结束,当非守护线程结束后,守护线程就没有存在的必要了。

线程类MyThread1,MyThread2

public class MyThread1 extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(getName() + "@" + i);
        }
    }
}
public class MyThread2 extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName() + "@" + i);
        }
    }
}

执行类ThreadDemo

public class ThreadDemo {

    public static void main(String[] args) {

        MyThread1 t1 = new MyThread1();
        MyThread2 t2 = new MyThread2();

        t1.setName("女神");
        t2.setName("备胎");

        // 线程2设置为守护线程
        t2.setDaemon(true);

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

7、线程的让出

public static void yield() 出让线程/礼让线程,让出当前执行线程CPU的执行权

线程类MyThread

public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName() + "@" + i);
            // 出让当前CPU的执行权
            Thread.yield();
        }
    }
}

执行类ThreadDemo

public class ThreadDemo {
    public static void main(String[] args) {

        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();

        t1.setName("飞机");
        t2.setName("坦克");

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

8、线程插队

public final void join() 插入线程/插队线程,讲指定的线程插入到main(当前线程)之前执行

线程类MyThread

public class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName() + "@" + i);
        }
    }
}

执行类ThreadDemo

public class ThreadDemo {

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

        MyThread t1 = new MyThread();
        t1.setName("土豆");
        t1.start();
        // 将t1(土豆) 线程插入到main线程(当前线程)之前
        t1.join();

        // 执行在main线程中
        for (int i = 0; i < 10; i++) {
            System.out.println("main线程" + i);
        }
    }
}

9、同步代码块

在需要同步的代码块中加入synchronized(当前类字节码文件)

线程类MyThread

public class MyThread extends Thread {

    /**
     * 票号,所有的类都共享该票号
     */
    static int ticket = 0;

    @Override
    public void run() {
        while (true) {
            // 使用同步代码块枷锁,锁对象必须是唯一的才行(使用当前类字节码)
            synchronized (MyThread.class) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                if (ticket < 100) {
                    ticket++;
                    System.out.println(getName() + "正在卖第" + ticket + "张票!");
                } else {
                    break;
                }
            }
        }
    }
}

执行类ThreadDemo

public class ThreadDemo {

    public static void main(String[] args) {

        /*
         * 需求
         *       某电影院有100张票,只有三个买票窗口,使用多线程设计一个模拟程序来卖票
         * 利用同步代码块来完成
         */

        // 创建线程对象
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        MyThread t3 = new MyThread();

        // 起名字
        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        // 开启线程
        t1.start();
        t2.start();
        t3.start();
    }
}

10、同步方法

将需要同步的代码抽取为一个方法,并使用synchronized进行修饰

线程类MyRunnable

public class MyRunnable implements Runnable {

    int ticket = 0;

    @Override
    public void run() {
        // 1.写循环
        while (true) {
            // 2.同步代码块(同步方法)
            if (method()) {
                break;
            }
        }
    }

    // 3.同步方法(从同步代码块中抽取出来)
    private synchronized boolean method() {
        // 4.共享代码是否到了末尾
        if (ticket == 1000) {
            return true;
        } else {
            ticket++;
            System.out.println(Thread.currentThread().getName() + "在卖第" + ticket + "张票");
        }
        return false;
    }
}

执行类ThreadDemo

public class ThreadDemo {

    public static void main(String[] args) {

        /*
         * 需求
         *       某电影院有100张票,只有三个买票窗口,使用多线程设计一个模拟程序来卖票
         *  利用同步方法来完成
         */

        MyRunnable mr = new MyRunnable();

        Thread t1 = new Thread(mr);
        Thread t2 = new Thread(mr);
        Thread t3 = new Thread(mr);

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

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

    }
}

11、线程锁

lock() 配合使用可以达到synchronized相同操作

线程类MyThread

public class MyThread extends Thread {

    static int ticket = 0;

    // 只有一把锁
    static Lock lock = new ReentrantLock();

    @Override
    public void run() {
        while (true) {
            // 2.同步代码块
            // synchronized (MyThread.class) {
            lock.lock(); // 加锁
            // 3.判断
            try {
                if (ticket == 100) {
                    break;
                } else {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    ticket++;
                    System.out.println(getName() + "在卖第" + ticket + "张票");
                }
            }finally {
                lock.unlock(); // 释放锁
            }
            //   }
        }

    }
}

执行类ThreadDemo

public class ThreadDemo {
    public static void main(String[] args) {

        /*
         * 需求:
         *      某电影院目前正在上映国产电影,共有100张票,3个窗口
         *      使用JDK的lock实现
         */
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        MyThread t3 = new MyThread();

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

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

12、死锁问题

死锁原因常见于锁的嵌套等操作,导致相互获取不到资源产生的等待问题

线程类MyThread

public class MyThread extends Thread{

    static Object objA = new Object();
    static Object objB = new Object();

    @Override
    public void run() {
        // 1.循环
        while (true){
            if ("线程A".equals(getName())){
                synchronized (objA){
                    System.out.println("线程A拿到了A锁,准备拿B锁");
                    synchronized (objB){
                        System.out.println("线程A拿到了B");
                    }
                }
            }else if ("线程B".equals(getName())){
                if ("线程B".equals(getName())){
                    synchronized (objB){
                        System.out.println("线程B拿到了B锁,准备拿A锁");
                        synchronized (objA){
                            System.out.println("线程B拿到了A锁,顺利执行完了一轮");
                        }
                    }
                }
            }
        }
    }
}

执行类ThreadDemo

public class ThreadDemo {

    public static void main(String[] args) {
        /*
         * 需求:死锁
         */
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();

        t1.setName("线程A");
        t2.setName("线程B");

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

13、等待唤醒机制(消费者模式)

生产者(Cook) => 中间者(Desk) <= 消费者(Foodie)

线程类Cook,Foodie

/**
* 厨师
*/
public class Cook extends Thread {

    /**
     * 1.循环
     * 2.同步代码块
     * 3.判断共享数据是否到末尾(到了)
     * 4.判断共享数据是否到末尾(没有,执行核心逻辑)
     */

    @Override
    public void run() {
        // 1.循环
        while (true) {
            // 2.同步代码块
            synchronized (Desk.lock) {
                // 3.判断共享数据是否到末尾(到了)
                if (Desk.count == 0) {
                    break;
                } else {
                    // 4.判断共享数据是否到末尾(没有,执行核心逻辑)

                    // 判断桌子上是否有食物
                    if (Desk.foodFlag == 1) {
                        // 如果有 就等待
                        try {
                            Desk.lock.wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }else {
                        // 如果没有 就制作
                        System.out.println("厨师做了一碗面条");
                        // 修改桌子上食物状态
                        Desk.foodFlag = 1;
                        // 叫醒等待的消费者开吃
                        Desk.lock.notifyAll();
                    }
                }
            }
        }
    }
}
/**
* 客人
*/
public class Foodie extends Thread {

    /**
     * 1.循环
     * 2.同步代码块
     * 3.判断共享数据是否到末尾(到了)
     * 4.判断共享数据是否到末尾(没有,执行核心逻辑)
     */

    @Override
    public void run() {

        // 1.循环
        while (true) {
            // 2.同步代码块
            synchronized (Desk.lock) {
                // 3.判断共享数据是否到了末尾(到了末尾,线程执行完毕)
                if (Desk.count == 0) {
                    break;
                } else {
                    // 4.判断共享数据是否到了末尾(没有到末尾,执行核心逻辑)
                    // 先判断桌子上是否有面条
                    if (Desk.foodFlag == 0) {
                        // 没有就等待
                        try {
                            Desk.lock.wait(); // 让当前线程跟锁进行绑定
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    } else {
                        // 把吃的总数减一
                        Desk.count--;
                        // 有就开吃
                        System.out.println("吃货正在吃面条,还能吃" + Desk.count + "碗!");
                        // 吃完后唤醒厨师继续制作
                        Desk.lock.notifyAll();
                        // 修改桌子状态
                        Desk.foodFlag = 0;
                    }
                }
            }
        }
    }
}
/**
* 中间者 桌子
*/
public class Desk {
    /*
     * 控制生产者和消费者的执行
     */

    /**
     * 桌子上是否有面条 0:没有 1:有
     */
    public static int foodFlag = 0;

    /**
     * 总个数,最多能吃10碗
     */
    public static int count = 10;

    // 锁对象
    public static Object lock = new Object();

}

执行类ThreadDemo

public class ThreadDemo {

    public static void main(String[] args) {
        /*
         * 需求:完成生产者和消费者(等待唤醒机制)的代码
         *      实现线程轮流交替的执行效果
         *
         * 生产者 ===> 中间者 <=== 消费者
         *
         */

        // 创建线程对象
        Cook cook = new Cook();
        Foodie foodie = new Foodie();

        cook.setName("厨师");
        foodie.setName("客人");

        // 开启线程
        cook.start();
        foodie.start();

    }
}

14、阻塞队列下的等待唤醒机制

生产者和消费者必须使用同一个队列ArrayBlockingQueue

生产者 => ArrayBlockingQueue <= 消费者

线程类Cook,Foodie

/**
* 厨师
*/
public class Cook extends Thread {

    ArrayBlockingQueue<String> queue;

    public Cook(ArrayBlockingQueue<String> queue) {
        this.queue = queue;
    }


    @Override
    public void run() {

        while (true) {
            // 不断的把面条放入阻塞队列中
            try {
                // put方法底层实现了锁操作,所以无需加锁
                queue.put("面条");
                System.out.println("厨师放了一碗面条");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}
/**
* 客人
*/
public class Foodie extends Thread {

    ArrayBlockingQueue<String> queue;

    public Foodie(ArrayBlockingQueue<String> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        while (true) {
            // 不断的从阻塞队列中获取面条
            // peek方法底层实现了锁操作,所以无需加锁
            String food = null;
            try {
                food = queue.take();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("客户吃了 " + food);
        }
    }
}

执行类ThreadDemo

public class ThreadDemo {

    public static void main(String[] args) {

        /*
         * 需要:利用阻塞队列完成生产者和消费者(等待唤醒机制)的代码
         * 细节:
         *      生产者和消费者必须使用同一个队列
         */

        // 1.创建阻塞队列(容量位1 )
        ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(1);

        // 2.创建线程对象,并把阻塞队列传递过去
        Cook cook = new Cook(queue);
        Foodie foodie = new Foodie(queue);

        // 3.开启线程
        cook.start();
        foodie.start();
    }
}

线程池

1、线程池的创建

ExecutorService newCachedThreadPool() 创建一个没有上限的线程池

ExecutorService new FixedThreadPool(int nThread) 创建有上限的线程池

线程类MyRunnable

public class MyRunnable implements Runnable {

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

执行类MyThreadPoolDemo

public class MyThreadPoolDemo {

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

        /*
         * public static ExecutorService newCachedThreadPool() 创建一个没有上限的线程池
         * public static ExecutorService new FixedThreadPool(int nThread) 创建有上限的线程池
         */

        fixedThreadPool();
    }

    public static void newCachedThreadPool() throws InterruptedException {
        // 1.获取线程池对象
        ExecutorService pool1 = Executors.newCachedThreadPool();

        // 2.提交任务
        pool1.submit(new MyRunnable());
        Thread.sleep(1000);
        pool1.submit(new MyRunnable());
        Thread.sleep(1000);
        pool1.submit(new MyRunnable());
        Thread.sleep(1000);
        pool1.submit(new MyRunnable());
        Thread.sleep(1000);
        pool1.submit(new MyRunnable());


        // 3.销毁线程池
        pool1.shutdown();
    }

    public static void fixedThreadPool() throws InterruptedException {
        // 创建三个线程
        ExecutorService pool1 = Executors.newFixedThreadPool(3);
        // 2.提交任务
        pool1.submit(new MyRunnable());
        Thread.sleep(1000);
        pool1.submit(new MyRunnable());
        Thread.sleep(1000);
        pool1.submit(new MyRunnable());
        Thread.sleep(1000);
        pool1.submit(new MyRunnable());
        Thread.sleep(1000);
        pool1.submit(new MyRunnable());

        // 3.销毁线程池
        pool1.shutdown();
    }
}

2、自定义线程池

(核心线程数量, 最大线程数量, 空闲线程最大存活时间, 任务队列, 创建线程工厂, 任务的拒绝策略)
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
	参数一: 核心线程数量      不能小于0,
	参数二: 最大线程数       不能小于等于0,最大数量 >= 核心线程数量,
	参数三: 控线线程最大存活时间      不能小于0,
	参数四: 线程存活时间单位        用TimeUnit指定,
	参数五: 任务队列        不能为null,
	参数六: 创建线程工厂      不能为null,
	参数七: 任务的拒绝策略     不能为null
);

例子,MyThreadPoolDemo1

public class MyThreadPoolDemo1 {

    public static void main(String[] args) {
        // 自定义线程池
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                // 核心线程数量,不能小于0
                3,
                // 最大线程数不能小于等于0,最大数量 >= 核心线程数量
                6,
                // 控线线程最大存活时间
                60,
                // 线程存活时间单位,用TimeUnit指定
                TimeUnit.SECONDS,
                // 任务队列
                new ArrayBlockingQueue<>(3),
                // 创建线程工厂
                Executors.defaultThreadFactory(),
                //  任务的拒绝策略
                new ThreadPoolExecutor.CallerRunsPolicy()
        );

        // 提交任务到线程池
        pool.submit(() -> {
            System.out.println(Thread.currentThread().getName());
        });
    }
}

标签:JUC,多线程,Thread,void,MyThread,线程,new,完整版,public
From: https://www.cnblogs.com/MineLSG/p/18210998

相关文章

  • 《庆余年2》迅雷下载高清完整版[第二季1080p][全集BT下载]
    《庆余年2》是根据猫腻所撰写的同名小说改编的电视剧,于2020年12月7日在湖南卫视首播。作为继第一季《庆余年》取得巨大成功后的续作,第二季再次席卷荧屏,引起了广大观众的热议与关注。 故事发生在北宋年间,曹操统一北方后,开始对南方展开攻势。而这一切与主人公张小凡......
  • Python多线程案例分析
    接下来,我们将在之前的基础上进一步扩展多线程爬虫案例,增加以下功能:1.动态URL发现与添加:爬虫在解析页面时,能够发现并添加新的URL到队列中。2.设置请求头:模拟浏览器行为,设置请求头中的`User-Agent`。3.使用会话:使用`requests.Session()`对象来保持连接,提高效率。4.避免重......
  • 进程间通信(管道),多线程
    Ⅰ进程间通信(管道)【一】引入借助于消息队列,进程可以将消息放入队列中,然后由另一个进程从队列中取出。这种通信方式是非阻塞的,即发送进程不需要等待接收进程的响应即可继续执行。multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的进程间通信(IPC)方式二......
  • Java实验五: Java多线程程序设计(头歌)
    一、线程接力编写一个应用程序,除了主线程外,还有三个线程:first、second和third。first负责模拟一个红色的按钮从坐标(10,60)运动到(100,60);second负责模拟一个绿色的按钮从坐标(100,60)运动到(200,60)。third线程负责模拟一个蓝色的按钮从坐标(200,60)运动到(300,60)。第一步以下是ideajdk1.8的教......
  • 多线程
    【一】什么是线程在操作系统中,每一个进程都有一块内存空间地址,你的程序就泡在这块内存地址上不可能一个程序只有一个进程在处理所有数据和逻辑于是就有了线程这个概念:在进程内部开设的处理程序的进程操作系统-->运行一个程序叫进程--->进程里面又开了一个进程--->改名叫......
  • 电视剧《庆余年2》第二季全集完整版高清迅雷下载1080p/720p[HD]
    电视剧《庆余年2》作为继第一部的续集,持续了第一部的高燃剧情和精彩演绎,再次引起了广大观众的关注与热议。本剧以庆帝刘弼铭为主线,讲述了他在林殊之死后继续战斗的故事。此次续集的推出,再度掀起了一股庆余年的热潮,并展现了中国电视剧在制作和创作方面的高水平和创新力。......
  • C++ 多线程编程要点总结
    C++多线程编程要点总结:选择合适的线程库:C++11引入了 <thread> 头文件,提供了对线程的原生支持。也可以使用第三方库,如Boost.Thread,它提供了更多高级功能和更好的跨平台兼容性。线程创建与管理:使用 std::thread 类创建新线程,并传入函数或可调用对象作为线程的入口......
  • 多线程和多进程 - 初窥
    一、说明在平常工作中,我们使用top命令查看一台linux服务器的cpu使用情况时,会发现某个进程的cpu使用率会超过100%,这是为什么?二、举例实验环境为CentOS7.6+Python2.71.多线程、多进程在操作系统中的表现形式我们首先看两个例子,test1.py和test2.py,都是执行死循环,test1.py两......
  • PHP的多样化执行方式(parallel PHP多线程实现,原生协程实现,多进程实现,ZTS、NTS、TS又是
    进程、线程、协程进程:应用程序的启动实例,运行起的代码叫进程,有独立的内存空间,类比工厂的P个(P=1单进程,P>1多进程)车间。线程:线程是CPU调度的最小单位,是进程内的执行单元,多个线程共享所属进程的资源。类比车间内的T个员工(T=1单线程,T>1多线程)车间。协程:类似线程,协程是用户态(CPU受......
  • 多线程下使用List中的subList和remove方法产生的 java.util.ConcurrentModificationEx
    在说多线程操作List之前,我们先看下单线程下产生的问题:单线程List<Integer>listA=newArrayList<>();listA.add(1);listA.add(2);listA.add(3);listA.add(4);listA.add(5);listA.add(6);for(Integera:listA){......