栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java并发编程(一)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java并发编程(一)

Java并发编程 进程与线程 进程

程序由指令和数据构成,但这些指令要运行,数据要读写,就必须将指令加载在CPU,数据加载进内存,在指令运行过程中还需要用到磁盘、网络等设备,进程就是用来加载指令、管理内存、管理IO的当一个程序被运行,从磁盘加载带这个程序的代码到内存,此时就开启了一个进程进程就可以认为是程序的一个实例。 线程

一个进程可以分为一到多个线程一个线程就是一个指令流,将指令流中的一条条指令以一定的顺序交给CPU执行Java中线程作为最小的调度单位,进程最为资源分配的最小单位,在Windows中进程是不活动的,只是作为线程的容器 进程与线程的对比

进程基本上相互独立的,而线程存在于进程内,是进程的一个子集进程拥有共享的资源,如内存空间等,供其内部的线程共享进程间通信较为复杂

同一台计算机的进程通信称为 IPC(Inter-process communication)不同计算机之间的进程通信,需要通过网络,并遵守共同的协议,例如 HTTP 线程通信相对简单,因为它们共享进程内的内存,一个例子是多个线程可以访问同一个共享变量线程更轻量,线程上下文切换成本一般上要比进程上下文切换低 并行与并发

并发(concurrent)是同一时间应对(dealing with)多件事情的能力并行(parallel)是同一时间动手做(doing)多件事情的能力 Java线程 创建和运行线程 1. 直接使用Thread

// 创建一个线程对象
  Thread t = new Thread(){
            @Override
            public void run(){
            	//要运行的任务 
                log.debug("running");
            }
        };
        //设置线程的名字
        t.setName("t1");
        // 启动线程
        t.start();
2. 使用Runable配合Thread

这个方式可以使线程和任务分开执行

Thread代表线程Runable是可执行的任务

  Runnable runnable = new Runnable() {
            @Override
            public void run() {
                log.debug("running");
            }
        };
        // lambda 表达式写法
        // Runnable runnable1 = () ->{log.debug("running");};
        // 参数1是任务对象,参数2是线程的名字
        Thread thread = new Thread(runnable,"t2");
        thread.start();

与方法1比较

1是将线程和方法合并在了一起,2是把线程和任务分开使用Runable更容易与线程池等高级API配合用Runable让任务类脱离了Thread继承体系,更灵活 3. FutureTask配合Thread

FutureTask 能够接收 Callable 类型的参数,用来处理有返回结果的情况

   FutureTask futureTask  = new FutureTask<>(
   		new Callable() {
            @Override
            public Integer call() throws Exception {
                log.debug("running...");
                Thread.sleep(1000);
                return 100;
            }
        });
        Thread thread = new Thread(futureTask,"t3");

        thread.start();
        // 等待task返回
        log.debug("{}",futureTask.get());
start与run 调用Run
 public static void main(String[] args) {
        Thread t1 = new Thread("t1") {
            @Override
            public void run() {
                log.debug(Thread.currentThread().getName());
            }
        };
        t1.run();
        log.debug("完成。。。。。。");
    }

输出,由主线程来运行方法输出

22:03:29.423 [main] DEBUG c.Test09 - main
22:03:29.425 [main] DEBUG c.Test09 - 完成。。。。。。
调用start

将上述的run改成start,输出日志如下,两个输出以不同的线程输出

22:06:42.781 [t1] DEBUG c.Test09 - t1
22:06:42.781 [main] DEBUG c.Test09 - 完成。。。。。。
总结

直接调用 run 是在主线程中执行了 run,没有启动新的线程使用 start 是启动新的线程,通过新的线程间接执行 run 中的代码 sleep与yield

方法名static功能说明
sleep(long n)static让当前执行的线程休眠n毫秒,休眠时让出 cpu的时间片给其它线程
yield()static提示线程调度器让出当前线程对CPU的使用
sleep
    调用 sleep 会让当前线程从 Running 进入 Timed Waiting 状态(阻塞)其它线程可以使用 interrupt 方法打断正在睡眠的线程,这时 sleep 方法会抛出 InterruptedException睡眠结束后的线程未必会立刻得到执行建议用 TimeUnit 的 sleep 代替 Thread 的 sleep 来获得更好的可读性
yield
    调用 yield 会让当前线程从 Running 进入 Runnable 就绪状态,然后调度执行其它线程具体的实现依赖于操作系统的任务调度器
线程优先级的设定

线程对象可以通过setPriority();方法来设定优先级线程优先级会提示(hint)调度器优先调度该线程,但它仅仅是一个提示,调度器可以忽略它如果 cpu 比较忙,那么优先级高的线程会获得更多的时间片,但 cpu 闲时,优先级几乎没作用 join方法

join()方法分为有参和无参,

方法名static功能说明
join等待线程运行结束
join(long n)等待线程运行结束,最多等待 n毫秒
join()
  static int r1 = 0;
    static int r2 = 0;
    public static void main(String[] args) throws InterruptedException {
        test12();
    }
    private static void test12() throws InterruptedException {
        Thread t1 = new Thread(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            r1 = 10;
        });
        Thread t2 = new Thread(() -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            r2 = 20;
        });
        long start = System.currentTimeMillis();
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        long end = System.currentTimeMillis();
        log.debug("r1: {} r2: {} cost: {}", r1, r2, end - start);
    }

第一个 join:等待 t1 时, t2 并没有停止, 而在运行第二个 join:1s 后, 执行到此, t2 也运行了 1s, 因此也只需再等待 1s输出为

22:31:55.281 [main] DEBUG c.Test12 - r1: 10 r2: 20 cost: 2005
join(long n) 等待够时间
static int r1 = 0;
    static int r2 = 0;
    public static void main(String[] args) throws InterruptedException {
        test11();
    }
    public static void test11() throws InterruptedException {
        Thread t1 = new Thread(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            r1 = 10;
        });
        long start = System.currentTimeMillis();
        t1.start();
        // 线程执行结束会导致 join 结束
        t1.join(1500);
        long end = System.currentTimeMillis();
        log.debug("r1: {} r2: {} cost: {}", r1, r2, end - start);
    }

输出

22:34:22.580 [main] DEBUG c.Test11 - r1: 10 r2: 0 cost: 1006
等待超时
 static int r1 = 0;
    static int r2 = 0;
    public static void main(String[] args) throws InterruptedException {
        test13();
    }
    public static void test13() throws InterruptedException {
        Thread t1 = new Thread(() -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            r1 = 10;
        });
        long start = System.currentTimeMillis();
        t1.start();
        // 线程执行结束会导致 join 结束
        t1.join(1500);
        long end = System.currentTimeMillis();
        log.debug("r1: {} r2: {} cost: {}", r1, r2, end - start);
    }

输出

22:36:17.886 [main] DEBUG c.Test13 - r1: 0 r2: 0 cost: 1506
interrupt 方法

打断 sleep,wait,join 的线程,这几个方法都会让线程进入阻塞状态打断 sleep 的线程, 会清空打断状态,以 sleep 为例

 private static void test1() throws InterruptedException {
        Thread t1 = new Thread(()->{
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "t1");
        t1.start();
        Thread.sleep(500);
        t1.interrupt();
        log.debug(" 打断状态: {}", t1.isInterrupted());
    }

输出

java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at com.wjl.code01.Test01.lambda$test1$0(Test01.java:18)
	at java.lang.Thread.run(Thread.java:750)
22:39:48.973 [main] DEBUG c.Test01 -  打断状态: false

打断正常运行的线程,不会清空打断状态

 private static void test2() throws InterruptedException {
        Thread t2 = new Thread(()->{
            while(true) {
                Thread current = Thread.currentThread();
                boolean interrupted = current.isInterrupted();
                if(interrupted) {
                    log.debug(" 打断状态: {}", interrupted);
                    break;
                }
            }
        }, "t2");
        t2.start();
        Thread.sleep(500);
        t2.interrupt();
    }

输出

22:42:04.128 [t2] DEBUG c.Test01 -  打断状态: true
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/785874.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号