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

    进程和线程的概念

    进程

    几乎所有的操作系统都支持进程的概念。一个任务通常对应一个进程。进程具有如下特征:

    • 进程通常是独立存在的,拥有自己独立的资源。
    • 进程拥有自己的生命周期和各种不同的状态。
    • 多个进程可以在单个处理器上并发执行,多个进程之间不会互相响应。

    线程

    线程是cpu执行的最小单元,一个进程可以有多个线程。一个线程必须有一个父进程。线程可以拥有自己的堆栈,但不拥有系统资源。对 cpu 而言,在同一时间,只能执行一个线程。之所以看起来像是在同时执行,是因为cpu轮循的时间特别快。线程由进程来负责管理和调度。

    线程的生明周期

    在网上扒了一张图,足够清晰明了。

    Java线程具有五中基本状态

    新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();

    就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;

    运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就 绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;

    阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:

    1.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;

    2.同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;

    3.其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

    死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

    需要注意的是: wait() 、notify()、notifyAll() 方法是 Object 类的方法。

    java 中线程的创建和启动

    1.继承自 Thread 类创建线程:

    • 定义类继承自 Thread 类,重写该类的 run() 方法,run() 方法方法体代线程要执行的任务。因此,run() 方法也称线程执行体。
    • 创建定义的线程类的实例,即创建线程对象。
    • 调用线程对象的 start() 方法启动该线程。
        public class MyThread extends Thread {
            @Override
            public void run() {
                for (int i = 0; i < 1000; i++) {
                    System.out.println(getName() + "-----" + i);
                }
            }
        
            public static void main(String[] args){
                new MyThread().start();
                new MyThread().start();
            }
        }
    

    截取部分执行结果如下:

    2.实现Runnable接口创建线程:

    • 定义 Runnable 接口的实现类,并重写该接口的 run()方法,该 run() 同样是线程执行体。
    • 创建 Runnable 实现类的实例,将 Runnable 实现类的实例传入作为参数传入,创建 Thread 类的实例,作为线程对象。
    • 调用线程对象的 start() 方法启动线程。
        public class MyThread implements Runnable {
            @Override
            public void run() {
                for (int i = 0; i < 1000; i++) {
                    System.out.println(Thread.currentThread().getName() + "-----" + i);
                }
            }
    
            public static void main(String[] args){
                MyThread mt = new MyThread();
                new Thread(mt).start();
                new Thread(mt).start();
            }
        }
    

    截取部分执行结果如下:

    3.使用 Callable 和 Future 创建线程:

    • 创建 Callable 的实现类,并实现 call() 方法,call() 方法为线程执行体。泛型参数为 call() 返回值。
    • 创建 Callable 实现类的实例,并将该对象传入,创建 FutureTask 类的实例。该 FutureTask 的对象封装了 该 Callable 实例对象的返回值。
    • 创建 FutureTask 的实例,作为 target 传入,创建 Thread 类的对象,作为线程对象。
    • 调用线程对象的 start() 方法启动线程。
    • 如有必要,可以通过 FutureTask 对象的 get() 方法来获得线程执行结束后的返回值。
        public class MyCallable implements Callable<Integer> {
            @Override
            public Integer call() throws Exception {
                int i = 0;
                for (; i < 1000; i++) {
                    System.out.println(Thread.currentThread().getName() + "-----" + i);
                }
                return i;
            }
            public static void main(String[] args) {
                MyCallable mc = new MyCallable();
                FutureTask<Integer> task = new FutureTask<Integer>(mc);
                new Thread(task).start();
                try {
                    Thread.sleep(5000);// 可能做一些事情
                    System.out.println("----------" + task.get());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
            }
        }
    
    

    值得一提的是:虽然直接继承自 Thread 类的方式实现起来最为简单,但是由于java的类只能单继承,但可以实现多个接口。所以一般我们不采用该方式。另外,启动线程的方式,都是通过调用线程对象的 start() 方法,切莫不要直接调用 run() 方法,这样实际是把该线程类当作了一个普通类而已。

  • 相关阅读:
    document.getElementById("mytxt").style.left=""style.left在IE的FF中注意
    asp.net 用户控件中 使用相对路径的解决方法 图片路径问题(用户控件、图片路径) ,ResolveUrl
    探索 Block (一) (手把手讲解Block 底层实现原理)
    iOS 多线程开发 (概念与API简介)
    iOS 性能小点
    iOS runtime (二)(runtime学习之AutoCoding源码分析)
    探索 NSRunLoop (二)(NSRunLoop 自己动手实现SimpleRunLoop)
    iOS NSNotificationCenter (自己实现一个通知中心XMCNotificationCenter)
    iOS runtime (三)(runtime学习之YYModel源码分析)
    iOS runtime(一)(runtime 分析理解)
  • 原文地址:https://www.cnblogs.com/joy99/p/7482615.html
Copyright © 2011-2022 走看看