zoukankan      html  css  js  c++  java
  • 多线程学习-基础(一)Thread和Runnable实现多线程

           很久没记录一些技术学习过程了,这周周五的时候偶尔打开“博客园”,忽然让我产生一种重拾记录学习过程的想法,记录下学习研究过程的一点一滴,我相信,慢慢地就进步了!最近想学习一下多线程高并发,但是多线程在实际工作中操刀不多,对于多线程的理解也不够深入,很多地方都存在不确定性,这让我困惑,所以决定从头开始学习一下“多线程”,然后再慢慢研究“高并发”。那么直接记录学习过程吧!

          学习或巩固新的知识,需要好的资料和动手去实践,这样效果很明显。

       推荐一下我参考的一位博主的博客:https://www.cnblogs.com/yjd_hycf_space/p/7526608.html

    那么开始正式记录

    一、进程和线程的区别

    进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程。(进程是资源分配的最小单位)
    线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。(线程是cpu调度的最小单位)
    线程和进程一样分为五个阶段:创建、就绪、运行、阻塞、终止。
    多进程是指操作系统能同时运行多个任务(程序)。
    多线程是指在同一程序中有多个顺序流在执行。 

    在java中要想实现多线程,有两种手段,一种是继续Thread类,另外一种是实现Runable接口.

    二、扩展java.lang.Thread类

    简单例子:

     创建一个线程类:

    package com.jason.threads;
    /**
     *  多线程学习(一)1.1
     * @function  多线程-继承Tread类来实现多线程
     * @author 小风微凉
     * @time  2018-4-21 上午10:10:09
     */
    public class Thread_1_Action extends Thread {
        private String thname;
        public Thread_1_Action(String name){
            this.thname=name;
        }
        public void run(){
            for(int i=0;i<5;i++){
                System.out.println(thname+"运行:"+i);
                try {
                    sleep((int) (Math.random()*10));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }    
    }

     运行线程:

    package com.jason.start;
    import com.jason.threads.Thread_1_Action;
    public class StartAction_1 {
        /**
         * 测试:多线程继承Thread类
         * @param args
         */
        public static void main(String[] args) {
            Thread_1_Action thread1=new Thread_1_Action("1号线程");
            Thread_1_Action thread2=new Thread_1_Action("2号线程");
            thread1.start();
            thread2.start();
        }
    }

     执行结果:

    2号线程运行:0
    1号线程运行:0
    2号线程运行:1
    2号线程运行:2
    1号线程运行:1
    1号线程运行:2
    2号线程运行:3
    1号线程运行:3
    2号线程运行:4
    1号线程运行:4

     分析总结:
    
    /**
    * 总结:
    * 进程:操作系统(OS)资源分配的最小单位
    * 线程:cpu可调度的最小单位,多个线程共享所在进程的资源。
    * 不论进程、线程都有5个状态:创建-就绪-运行-阻塞-终止
    * (1)一个线程的start()方法被调用,并不意味着这个线程就会立马被cpu调用,而是由创建状态转变成可执行状态(也即:就绪状态)。
    * (2)多个线程的被cpu调用的顺序是不固定的,为乱序执行,这个要操作系统来决定。
    * (3)Thread.sleep()方法的目的是为了避免让一个线程持续占用cpu的资源,以空出资源给其他线程来使用。
    * (4)多线程的执行顺序每次都是不同的,乱序执行。
    * (5)只有乱序执行的代码才有必要设计为多线程。
    * (6)一个线程调用了start()方法后,如果再次去调用start(),会抛出java.lang.IllegalThreadStateException异常
    */

     三、实现java.lang.Runnable接口

    采用Runnable也是非常常见的一种,我们只需要重写run方法即可。下面也来看个实例。

     简单例子:

    创建一个Java类实现Runnable接口,并实现run()方法

    package com.jason.threads;
    /**
     * 多线程学习(一)1.2
     * @function  多线程-实现Runnable接口来实现多线程
     * @author 小风微凉
     * @time  2018-4-21 上午10:47:55
     */
    public class Thread_2_Action implements Runnable{
        private String thname;
        public Thread_2_Action(String name){
            this.thname=name;
        }
        public void run() {
            for(int i=0;i<5;i++){
                System.out.println(thname+"运行:"+i);
                try {
                    Thread.sleep((int)Math.random()*10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }        
        }
    }

     执行线程:

    package com.jason.start;
    
    import com.jason.threads.Thread_2_Action;
    
    public class StartAction_2 {
    
        /**
         * 测试:多线程实现Runnable接口
         * @param args
         */
        public static void main(String[] args) {
            new Thread(new Thread_2_Action("1号线程")).start();
            new Thread(new Thread_2_Action("2号线程")).start();
    
        }
    
    }

      运行结果:

    1号线程运行:0
    2号线程运行:0
    2号线程运行:1
    1号线程运行:1
    2号线程运行:2
    1号线程运行:2
    2号线程运行:3
    1号线程运行:3
    1号线程运行:4
    2号线程运行:4

    分析总结:
    /**
     * 总结:
     * (1)Thread_2_Action类通过实现Runnable接口,使得该类有了多线程的特征。
    * (2)run()方法是多线程程序的一个约定。所有的多线程代码都在run()方法里面。 * (3)Thread类也是一个实现了Runnable接口的类:class Thread implements Runnable * 程序说明: * 在启动多线程的时候,需要通过Thread类的构造器Thread(Runnable target)构造出对象,然后调用Tread对象的start() * 方法来运行多线程代码。实际上所有的多线程都是通过运行Thread的start()方法来运行的。因此,不管是扩展Thread类还是实现Runnable * 接口来实现多线程,最终都是Thread对象的API来控制线程的,熟悉Thread类的API是多线程编程的基础。
    */

     四、Thread和Runnable的区别

    /**
         * 总结:Thread和Runnable的区别
         *         如果一个类继承了Thread,则不适合资源共享,但是如果实现了Runnable接口的话,则很容易实现资源共享。
         * 实现Runnable接口比继承Thread类所具有的优势:
         * (1):适合相同的程序代码的线程去处理同一个资源。
         * (2):可以避免Java中的单继承限制。
         * (3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。
         * (4):线程池中只能放置实现了Runnable或callable类线程,不能直接放入继承Thread类的线程。
         * 特别说明一下:
         *    main()方法其实也是一个线程。在Java中线程都是同时启动的,至于什么时候,哪个先启动,完全看谁先得到cpu的资源。
         * 在Java中,每次执行程序至少要启动2个线程,一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,
         * 实际上都会启动一个JVM,每个JVM都会在操作系统(OS)中启动一个进程。
         */
  • 相关阅读:
    Unknown host mirrors.opencas.cn You may need to adjust the proxy settings in Gradle 报错及解决办法
    Design editor is unavaiable until next gradle sync报错及解决办法
    mkdir创建目录失败
    读书笔记之梦断代码(三)
    Android学习——更新数据
    Android学习——添加数据
    Android学习——升级数据库
    Android学习——创建数据库
    开课第十一周周总结
    Android学习——数据库简介
  • 原文地址:https://www.cnblogs.com/newwind/p/8901792.html
Copyright © 2011-2022 走看看