zoukankan      html  css  js  c++  java
  • java多线程

    1.进程和线程的区别:

        每个正在系统上运行的程序都是一个进程。每个进程包含一到多个线程。线程是一组指令的集合,或者是程序的特殊段,它可以在程序里独立执行。也可以把它理解为代码运行的上下文。所以线程基本上是轻量级的进程,它负责在单个程序里执行多任务。通常由操作系统负责多个线程的调度和执行。

       总结:进程是所有线程的集合,每一个线程是进程中的一条执行路径。

    2.为什么要使用多线程

     案例:如果一个工人修建一条1000米长的铁路需要10个小时,为了尽快完成工期,需要在一个小时内完成所有的铁路修建,如何解决呢?

    此时可以在加派9个工人,最后就是10个工人一起修建(考虑每个工人的修建速度一样)则只需要1个小时就可以完成.

    同样:使用多线程可以提高程序的效率.

    3.在java中如何创建多线程

      1.继承Thread类,重写run方法

    package com.thread;
    
    public class ThreadDemo extends Thread {
        @Override
        public void run() {
            System.out.println("继承Thread重写run方法");
        }
    
        public static void main(String[] args) {
            ThreadDemo threadDemo = new ThreadDemo();
            threadDemo.start();
        }
    }
    输出:继承Thread重写run方法

    注意:启动一个线程是用的.start()方法 而不是直接调用的run方法,如果直接调用run方法只是实例化的一个方法调用,根本没有启动一个线程

    思考:开启一个线程以后,该线程和main方法的执行先后顺序?

     

    package com.thread;
    
    public class ThreadDemo extends Thread {
        @Override
        public void run() {
            System.out.println("继承Thread重写run方法");
        }
    
        public static void main(String[] args) {
            System.out.println("main方法开始运行");
            ThreadDemo threadDemo = new ThreadDemo();
            threadDemo.start();
            System.out.println("main方法结束");
        }
    }

    输出结果:

    main方法开始运行
    main方法结束
    继承Thread重写run方法

    从输出结果可以看出,主程序的运行结束与否和新创建的线程运行情况无关,即使主线程运行完成,此时可能用户线程还在运行,不会随着主线程消亡而结束(守护线程则会)

     2.实现Runnable接口的方法

      

    package com.thread;
    
    public class RunnableDemo implements Runnable {
        public void run() {
            System.out.println("实现Runnable接口重写run方法");
        }
    
        public static void main(String[] args) {
            RunnableDemo runnableDemo = new RunnableDemo();
            Thread thread = new Thread(runnableDemo);
            thread.start();
        }
    }

    输出结果:

    实现Runnable接口重写run方法

     3.使用匿名内部类的方法创建多线程

     public static void main(String[] args) {
            new Thread(new Runnable() {
                public void run() {
                    System.out.println("匿名内部类的方法创建线程运行run方法");
                }
            }).start();
    
        }

    4.使用Callabel接口创建一个具有返回值的线程

    package com.thread;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    public class CallableThreadDemo implements Callable<String> {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            CallableThreadDemo callableThreadDemo = new CallableThreadDemo();
            FutureTask<Integer> futureTask = new FutureTask(callableThreadDemo);
            new Thread(futureTask, "有返回值的线程").start();
            System.out.println(futureTask.get());
        }
    
        public String call() throws Exception {
            return "我是线程 Callable接口的返回值哟";
        }
    
    
    }

    输出结果:

    我是线程 Callable接口的返回值哟

    5.使用线程池创建线程(后续补充)

    4. 在创建线程的时候使用Thread继承好还是使用Runnable接口好

    答:使用接口好,接口可以多继承

     

    5.常用的线程API

      1.获取当前线程对象的方法:currentThread()

      2.启动线程:.start()

      3.休眠线程:sleep(时间)cpu执行其他线程,但是不会释放当前线程已经拥有的锁

      4.停止线程:stop()

    6.线程的分类

     线程分成两类

      1.用户自定义线程:该线程不会随着主线程死亡而死亡,可以理解成main方法执行完毕以后,自定义线程还在执行

      2.守护线程:主线程执行完毕以后守护线程就自动死亡,可以通过thread.setDaemon(true)将该线程设置为守护线程

    7.线程的状态(重点)

      1.新建状态:new Thread()表示一个线程的创建,但是此时线程还并没有开始执行

     2.就绪状态:当前线程调用start()的时候 表示线程已经就绪,此时等待cpu调度

     3.运行状态:如果当前线程获取到了cpu的执行权,则开始运行该程序(执行run方法)

     4.死亡状态:run方法正常的执行完毕,或者run方法里面执行错误,该错误没有被捕获也会导致线程死亡(和main方法一样如果程序出错,没有捕获异常,则程序不会继续执行)

     5.阻塞状态:导致线程阻塞的情况有很多场景:比如调用sleep()方法,在同步锁当中执行一个方法的时候,没有获取到该方法的锁也会阻塞。如果操作数据库的时候IO时间较长,该线程也会阻塞  在调用sleep()方法以后,休眠时间到了,重新获取到cpu的执行权,则该线程又进入到运行状态

    8.设置线程的优先级和如何让多个线程优先执行一个线程

     优先级:现代操作系统基本采用时分的形式调度运行的线程,线程分配得到的时间片的多少决定了线程使用处理器资源的多少,也对应了线程优先级这个概念。在JAVA线程中,通过一个int priority来控制优先级,范围为1-10,其中10最高,默认值为5。可以通过 Thread.setPriority设置线程的优先级,设置优先级并不是每次都执行这个线程,只是会优先于这个线程

     顺序性:如果有三个线程,你先让线程2先执行,执行完成以后 在执行线程1,最后在执行线程3 使用join

     

    package com.thread;
    
    public class ThreadDemo extends Thread {
        @Override
        public void run() {
            String name = currentThread().getName();
            System.out.println(name + "继承Thread重写run方法");
        }
    
        public static void main(String[] args) throws InterruptedException {
            ThreadDemo threadDemo1 = new ThreadDemo();
            threadDemo1.setName("线程1");
            ThreadDemo threadDemo2 = new ThreadDemo();
            threadDemo2.setName("线程2");
            ThreadDemo threadDemo3 = new ThreadDemo();
            threadDemo3.setName("线程3");
            threadDemo2.start();
            threadDemo2.join();
            threadDemo1.start();
            threadDemo1.join();
            threadDemo3.start();
    
        }
    }

    输出结果:

    线程2继承Thread重写run方法
    线程1继承Thread重写run方法
    线程3继承Thread重写run方法

     

  • 相关阅读:
    WPF DelegateCommand 出现Specified cast is not valid
    WPF DelegateCommand 出现Specified cast is not valid
    WPF DelegateCommand 出现Specified cast is not valid
    win10 sdk 是否向下兼容
    win10 sdk 是否向下兼容
    win10 sdk 是否向下兼容
    PHP extract() 函数
    PHP end() 函数
    PHP each() 函数
    PHP current() 函数
  • 原文地址:https://www.cnblogs.com/920913cheng/p/11340597.html
Copyright © 2011-2022 走看看