zoukankan      html  css  js  c++  java
  • 如何创建线程详解(二)

    1、在 Windows 操作系统中创建进程

      在 windows 操作系统中,我们创建一个进程通常就是打开某个应用软件,这便在电脑中创建了一个进程。更原始一点的,我们在命令提示符中来做(我们以打开记事本这个进程为例):

      第一步:windows+R,输入cmd,打开 cmd 命令提示符

          

      第二步:在命令提示符中输入 notepad,按 Enter 键便会弹出记事本应用软件

          

     

     PS:常用的windows 应用软件命令

        1、regedit:打开注册表编辑器

        2、control:打开控制面板

        3、msconfig:打开系统配置

        4、gpedit.msc:打开本地组策略

        5、explorer:打开资源管理器

        6、taskmgr:任务管理器

        7、logoff:直接注销计算机

        8、osk:打开屏幕键盘

        9、calc:打开计算器

        10、mspaint:调出画图软件

        11、dxdiag:查看电脑详细配置信息

        12、mstsc:打开远程桌面连接

        13、systeminfo:查看计算机基本信息

        14、notepad:打开记事本

          

     

    2、在 Java 中创建进程

     

    第一种方法:通过 Runtime 类的 exec() 方法来创建进程

    1
    2
    public class Runtime
    extends Object<br>①、表示当前进程所在的虚拟机实例,每个Java应用程序都有一个Runtime类的Runtime ,允许应用程序与运行应用程序的环境进行接口。<br>②、由于任何进程只会运行与一个虚拟机实例当中,即只会产生一个虚拟机实例(底层源码采用 单例模式)<br>③、当前运行时可以从getRuntime方法获得。 

       

     

      由上面源码可以看到,构造器私有化了,即外部我们不能 new 一个新的 Runtime 实例,而内部给了我们一个获取 Runtime 实例的方法 getRuntime() 。

     

    通过 Runtime 类创建一个 记事本的 进程

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class ProcessTest {
         
        public static void main(String[] args) throws Exception {
            Runtime run = Runtime.getRuntime();
            //打开记事本
            run.exec("notepad");
        }
     
    }

      

      

    第二种方法:通过 ProcessBuilder 创建线程

    1
    2
    3
    public final class ProcessBuilder
    extends Object<br>①、此类用于创建操作系统进程。
    ②、每个ProcessBuilder实例管理进程属性的集合。 start()方法使用这些属性创建一个新的Process实例。 start()方法可以从同一实例重复调用,以创建具有相同或相关属性的新子进程。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class ProcessTest {
         
        public static void main(String[] args) throws Exception {
            //打开记事本
            ProcessBuilder pBuilder = new ProcessBuilder("notepad");
            pBuilder.start();
        }
     
    }

      

     

      

    3、在 Java 中创建线程

    第一种方法:继承 Thread 类

    1
    2
    3
    public class Thread
    extends Object
    implements Runnable  

     

    步骤:1、定义一个线程类 A 继承于 java.lang.Thread 类

       2、在 A 类中覆盖 Thread 类的 run() 方法

       3、在 run() 方法中编写需要执行的操作

       4、在 main 方法(线程)中,创建线程对象,并启动线程

          创建线程类:A类 a = new A()类;

          调用 start() 方法启动线程:a.start();

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    package com.ys.thread;
     
    class Thread1 extends Thread{
        @Override
        public void run() {
            for(int i = 0 ; i < 10 ;i++){
                System.out.println("播放音乐"+i);
            }
        }
    }
     
    public class ThreadTest {
        public static void main(String[] args) {
            for(int i = 0 ; i < 10 ; i++){
                System.out.println("玩游戏"+i);
                if(i==5){
                    Thread1 th1 = new Thread1();
                    th1.start();
                }
            }
        }
     
    }

      结果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    玩游戏0
    玩游戏1
    玩游戏2
    玩游戏3
    玩游戏4
    玩游戏5
    玩游戏6
    玩游戏7
    玩游戏8
    玩游戏9
    播放音乐0
    播放音乐1
    播放音乐2
    播放音乐3
    播放音乐4
    播放音乐5
    播放音乐6
    播放音乐7
    播放音乐8
    播放音乐9

      注意:我们看结果,并不是出现 5 个先打游戏,然后在播放音乐,这是线程调度的结果,两个线程同时在争抢 CPU 的资源,即最后的结果,前面5个打游戏的必然先出现的,后面的啥时候出现播放音乐就看 CPU 怎么调度了,这是随机的。我们不能干涉。

     

     

    第二种方法:实现 Runnable 接口

    1
    2
    @FunctionalInterface
    public interface Runnable

      

    1、Runnable接口应由任何类实现,其实例将由线程执行。 该类必须定义一个无参数的方法,称为run 。
    2、该接口旨在为希望在活动时执行代码的对象提供一个通用协议。此类整个只有一个 run() 抽象方法

     

    步骤:1、定义一个线程类 A 实现于 java.lang.Runnable 接口(注意:A类不是线程类,没有 start()方法,不能直接 new A 的实例启动线程)

       2、在 A 类中覆盖 Runnable 接口的 run() 方法

       3、在 run() 方法中编写需要执行的操作

       4、在 main 方法(线程)中,创建线程对象,并启动线程

          创建线程类:Thread t = new Thread( new A类() ) ;

          调用 start() 方法启动线程:t.start();

     

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    class Runnable1 implements Runnable{
        @Override
        public void run() {
            for(int i = 0 ; i < 10 ;i++){
                System.out.println("播放音乐"+i);
            }
        }
    }
     
    public class RunnableTest {
        public static void main(String[] args) {
            for(int i = 0 ; i < 10 ; i++){
                System.out.println("玩游戏"+i);
                if(i==5){
                    Thread th1 = new Thread(new Runnable1());
                    th1.start();
                }
            }
        }
     
    }

      

     

     第三种方法:使用匿名内部类创建线程

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public static void main(String[] args) {
            for(int i = 0 ; i < 10 ; i++){
                System.out.println("玩游戏"+i);
                if(i==5){
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            for(int i = 0 ; i < 10 ;i++){
                                System.out.println("播放音乐"+i);
                            }
                        }
                    }).start();
                }
            }
        }

      

     

    注意:

    1、启动线程是调用 start() 方法,而不是 调用 run() 方法。

      解析:run()方法:在本线程内调用run()方法,和其他方法没有什么区别,可以重复多次调用;

         start()方法:启动一个线程,实际上还是调用该Runnable对象的run()方法。

         打开 Thread 类的源码,start()方法里面有一句:

            private native void start0();  //native 关键字:本地程序调用    

        native关键字指的是Java本地接口调用,即是使用Java调用本地操作系统的函数功能完成一些特殊的操作,而这样的代码开发在Java中几乎很少出现,因为Java的最大特点是可移植性,如果一个程序 只能在固定的操作系统上使用,那么可移植性就将彻底丧失,多线程的实现一定需要操作系统的支持,那么start0()方法实际上就和抽象方法很类似,没有方法体,而是交给JVM 去实现,即在windows下的JVM可能使用A方法实现start0(),在linux下的JVM可能使用B方法实现start0(),在调用时并不会关心具体是何方式实现了start0()方法,只会关心最终的操作结果,交给 JVM去匹配了不同的操作系统。

     

    2、不能多次启动同一个线程,即多次调用 start() 方法,只能调用一次,否则报错:

      

     

    作者:KeerDi —— 北方的后生

    出处:http://www.cnblogs.com/keerdi/

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    论文阅读笔记(七十二)【ICMR2020】:Compact Network Training for Person ReID
    论文阅读笔记(七十一)【CVPR2018】:Harmonious Attention Network for Person Re-Identification
    论文阅读笔记(七十)【CVPR2021】:Combined Depth Space based Architecture Search For Person Re-identification
    论文阅读笔记(六十九)【CVPR2021】:BiCnet-TKS: Learning Efficient Spatial-Temporal Representation for Video Person Re-Identification
    论文阅读笔记(六十八):图文跨模态行人检索(3篇)
    (一万小时计划)二月二日总结
    (一万小时计划)一月二十三日总结
    (一万小时计划)一月二十日总结
    (一万小时计划)一月二日总结
    (一万小时计划)十二月二十二日总结
  • 原文地址:https://www.cnblogs.com/123hll/p/6902310.html
Copyright © 2011-2022 走看看