Java并发编程基础

导读:本篇文章讲解 Java并发编程基础,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com


一、并发VS并行

  • 并发(concurrent)是同一时间应对(dealing with)多件事情的能力。并发是在同一实体上的多个事件,多个事件在同一时间间隔发生
  • 并行(parallel)是同一时间动手做(doing)多件事情的能力

二、进程VS线程

  • 进程:是系统进行资源分配和调度的基本单位(操作系统分配的资源和调度对象其实是CPU时间片)
  • 线程:是操作系统能够进行资源调度的最小单位,它被包含在进程中,是进程中实际运行单位。

进程是资源分配的最小单位。线程是程序执行的最小单位(线程是操作系统能够进行资源调度的最小单位,同一个进程中的线程也可以被同时调度到多个CPU上运行),线程也被称为轻量级进程。

内存共享:默认情况下,进程的内存无法与其他进程共享(进程间通信通过IPC进行)。线程共享由操作系统分配给其父进程的内存块。

三、多线程实现方式之继承Thread类

使用说明:1.重写Thread类中的run()方法,2.使用start()方法启动线程
注意:每次创建一个新的线程,都要新建一个Thread子类的对象

代码如下(示例):

/**
 * Java实现多线程的方式1
 * 继承Thread类,重写run方法
 */
class MyThread extends Thread {//线程主体类

    @Override
    public void run() {
        //这里可以写thread执行的任务内容
        System.out.println(Thread.currentThread().getName());
    }
}
public class demo1 {


    public static void main(String[] args) {

        for(int i=0;i<2;i++) {
            Thread t = new MyThread();
            t.start(); //调用Thread的start()方法启动线程
        }
    }
}

运行结果如下(示例):
在这里插入图片描述

四、多线程实现方式之实现Runnable接口

使用说明:1.重写run()方法,2.使用new Thread(Runnable接口实现类的对象).start()方法启动线程
注意:不论创建多少个线程,只需要创建一个Runnable接口实现类的对象

代码如下(示例):

class ImplRunnable implements Runnable{
    private volatile  int i = 0;
    @Override
    public void run() {
        //这里可以写thread执行的任务内容
        System.out.println(Thread.currentThread().getName()+"--"+ i++);

    }
}

public class demo2 {

    public static void main(String ards[]){
        Runnable implRunnable = new ImplRunnable();
        for(int i=0;i<5;i++){
            new Thread(implRunnable).start();
        }
    }

}

运行结果:
在这里插入图片描述

五、多线程实现方式之实现 Callable接口

前面两种创建方式都是复写 run 方法,都是 void 形式的,没有返回值。但是对于方式三来说,实现 Callable 接口,能够有返回值类型。

使用说明:1:实现 Callable 接口,implements Callable; 2:复写 call () 方法,call () 方法是线程具体逻辑的实现方法。

public class ImplCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        return "创建线程通过实现Callable接口";
    }
}
public class ImplCallableTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<String> future1 = new FutureTask<String>(new ImplCallable());
        Thread thread1 = new Thread(future1,"t1");
        thread1.start();
        System.out.println(future1.get());
    }
    
}

六、多线程join方法

说明:多线程环境下,如果需要确保某一线程执行完毕后才可继续执行后续的代码,就可以通过使用 join 方法完成这一需求设计

场景举例:
线程 1 :执行时间 5 秒钟;
线程 2 :执行时间 10 秒钟;
线程 3 :执行 8 秒钟。
需求:我们需要等 3 个线程都执行完毕后,再进行后续代码的执行。3 个线程执行完毕后,打印执行时间。

public class JoinDemo {
    public static void main(String[] args) {
        //线程1
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程1休眠5秒钟,执行完毕!");
            }
        });
        //线程2
        ImplRunnable implRunnable = new ImplRunnable();
        Thread thread2 = new Thread(implRunnable);
        //线程3
        Thread thread3 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(8000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程3休眠8秒钟,执行完毕!");
            }
        });
        long startTime = System.currentTimeMillis();
        thread1.start();
        thread2.start();
        thread3.start();
        //jion方法
        try{
            thread1.join();
            thread2.join();
            thread3.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("三个线程全部执行完毕,共用时: "+(endTime-startTime)+"毫秒");
    }
}

在这里插入图片描述

补充:

join()   //无参,线程全部执行完毕
join(long millis)  //有参,等待 millis 毫秒终止线程,假如这段时间内该线程还没执行完,也不会再继续等待。

六、多线程yield方法

当一个线程调用 yield 方法时,实际就是在暗示线程调度器当前线程请求让出自己的 CPU 使用权。

  1. 作用
    暂停当前正在执行的线程对象(及放弃当前拥有的 cup 资源),并执行其他线程。yield () 做的是让当前运行线程回到就绪状态,以允许具有相同优先级的其他线程获得运行机会。
  2. 目的:
    yield 即 “谦让”,使用 yield () 的目的是让具有相同优先级的线程之间能适当的轮转执行。
    但是,实际中无法保证 yield () 达到谦让目的,因为放弃 CPU 执行权的线程还有可能被线程调度程序再次选中。

例子:
创建一个线程,线程名为 threadOne;
打印一个数,该数的值为从 1 加到 10000000 的和;
不使用 yield 方法正常执行,记录总的执行时间;
加入 yield 方法,再次执行程序;
再次记录总执行时间。
期望结果:
未加入 yield 方法之前打印的时间 < 加入 yield 方法之后的打印时间。
因为 yield 方法在执行过程中会放弃 CPU 执行权并从新获取新的 CPU 执行权。

public class YieldDemo {
    public static void main(String[] args) {
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                long startTime = System.currentTimeMillis();
                int count = 0;
                for (int i = 1; i < 100000; i++) {
                    count += i;
                }
                long endtime = System.currentTimeMillis();
                System.out.println("总执行时间: " + (endtime - startTime) + " 毫秒, 结果 count = " + count);
            }
        });
        thread1.start();
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                long startTime = System.currentTimeMillis();
                int count = 0;
                for (int i = 1; i < 100000; i++) {
                    count += i;
                    Thread.yield();
                }
                long endtime = System.currentTimeMillis();
                System.out.println("总执行时间: " + (endtime - startTime) + " 毫秒, 结果 count = " + count);
            }
        });
        thread.start();
    }
}

在这里插入图片描述

七、 yield() VS sleep()

  • sleep()方法给其他线程运行机会时不考虑现场的优先级,因此会给低优先级的线程以运行的机会;
  • yield()方法只会给相同优先级或更高优先级的线程以运行机会;
  • 线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态;
  • sleep()方法声明会抛出InterruptedException,而yield()方法没有声明任何异常;
  • sleep()方法比yield()方法具有更好的移植性(跟操作系统CPU调度相关);

多线程优化之线程池

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/119833.html

(0)
seven_的头像seven_bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!