精华内容
下载资源
问答
  • 如何启动线程
    千次阅读
    2021-11-24 12:29:56

    创建一个线程有以下两种方式。

    • 直接创建一个 Thread 类对象,并给它的构造函数传递一个可调用的对象(callable object)。
    • 从 Thread 类定义一个派生类,并重载其构造函数__init__()和__run__()方法,然后创建一个该派生线程类的对象并传递一个可调用的对象。
      Thread 类的构造函数:
    threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)
    

    其中,参数 target 就是线程的__run__()方法调用的可调用对象,即线程的执行代码,如果不提供,则线程将什么也不做。参数 name 是这个线程的名字,如果不提供,则系统会提供一个默认的名字。参数 args 和 kwargs 分别是 tuple 和 dict 类型的(可变)参数,即传递给 target 对象的参数。
    通过 Thread 类对象的 start()方法可以启动一个线程。Thread 的 start()方法会调用 Thread 的__run__()方法执行构造函数的参数 target 指向的可调用对象,同时将参数 args 和 kwargs 传递给这个target 对象。
    下面的代码在主线程中创建了 5 个线程。每个线程的构造函数中接收了一个可调用对象,即函数 worker(args),在该构造函数中,还传递了一个 tuple 对象(i,)作为函数 worker()的参数 args:

    #thread_args.py 
    import threading 
    def worker(args): 
        print('I am a Worker with params %s'%args )
    print('This is the main thread!')
    threads = [] 
    for i in range(5): 
        t = threading.Thread(target=worker,args=(i,))
        threads.append(t)
        t.start()
    

    输出如下:

    This is the main thread! 
    I am a Worker with params 0 
    I am a Worker with params 1 
    I am a Worker with params 2 
    I am a Worker with params 3 
    I am a Worker with params 4 
    
    更多相关内容
  • 但是,如果我们调用了start方法,由于它内部使用了native方法来启动线程,它将导致一个新的线程被创建出来, 而我们的Thread实例, 就代表了这个新创建出来的线程, 并且由这个新创建出来的线程来执行Thread实例的run...

    本文源码基于jdk1.8 。

    Runnale接口

    我们看Thread类的定义知道,它实现了Runable接口

    public class Thread implements Runnable {
        ...
    }
    

    而Runnable接口的定义如下:

    @FunctionalInterface
    public interface Runnable {
        public abstract void run();
    }
    

    它只有一个抽象方法run。同时,该接口还被@FunctionalInterface注解标注,说明它是一个函数式接口(@FunctionalInterface是java 1.8版本之后引入的)。这意味着我们可以使用Lambda表达式来创建Runnable接口的实例,这个我们到后面再举例。

    线程创建

    在java中,创建一个线程,有且仅有一种方式:

    创建一个Thread类实例,并调用它的start方法。

    这写在了java语言规范中(参见The Java Language Specification, Java SE 8 Edition, P659,chapter17):

    Threads are represented by the Thread class. The only way for a user to create a thread is to create an object of this class; each thread is associated with such an object. A thread will start when the start() method is invoked on the corresponding Thread object.

    构造函数

    要创建一个Thread类的实例自然要通过构造函数,Thread的public构造函数有8个之多,但是他们本质上都调用了同一个init函数:

    public Thread() {
        init(null, null, "Thread-" + nextThreadNum(), 0);
    }
    public Thread(String name) {
        init(null, null, name, 0);
    }
    public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }
    public Thread(Runnable target, String name) {
        init(null, target, name, 0);
    }
    public Thread(ThreadGroup group, Runnable target) {
        init(group, target, "Thread-" + nextThreadNum(), 0);
    }
    public Thread(ThreadGroup group, String name) {
        init(group, null, name, 0);
    }
    public Thread(ThreadGroup group, Runnable target, String name) {
        init(group, target, name, 0);
    }
    public Thread(ThreadGroup group, Runnable target, String name, long stackSize) {
        init(group, target, name, stackSize);
    }
    

    可见,这八个public类型的构造函数只不过是给init的方法的四个参数分别赋不同的值, 这四个参数分别是:

    • ThreadGroup g(线程组)
    • Runnable target (Runnable 对象)
    • String name (线程的名字)
    • long stackSize (为线程分配的栈的大小,若为0则表示忽略这个参数)

    而init方法又调用了另一个init方法,设置了AccessController,以及inheritThreadLocals参数:

    /**
     * Initializes a Thread with the current AccessControlContext.
     * @see #init(ThreadGroup,Runnable,String,long,AccessControlContext,boolean)
     */
    private void init(ThreadGroup g, Runnable target, String name, long stackSize) {
        init(g, target, name, stackSize, null, true);
    }
    
    //上面那个init方法最终调用了下面这个方法:
    
    /**
     * Initializes a Thread.
     *
     * @param g the Thread group
     * @param target the object whose run() method gets called
     * @param name the name of the new Thread
     * @param stackSize the desired stack size for the new thread, or
     *        zero to indicate that this parameter is to be ignored.
     * @param acc the AccessControlContext to inherit, or
     *            AccessController.getContext() if null
     * @param inheritThreadLocals if {@code true}, inherit initial values for
     *            inheritable thread-locals from the constructing thread
     */
    private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc, boolean inheritThreadLocals) {
        ...
    }
    

    init方法中有一些关于线程组和访问控制上下文的设置,这里我们暂时就不深入讨论了。

    所以综上来看,我们最常用的也就两个参数:

    • Runnable target (Runnable 对象)
    • String name (线程的名字)

    而对于线程的名字,其默认值为"Thread-" + nextThreadNum(), nextThreadNum方法又是什么呢:

    /* For autonumbering anonymous threads. */
    private static int threadInitNumber;
    private static synchronized int nextThreadNum() {
        return threadInitNumber++;
    }
    

    可见,它就是一个简单的递增计数器,所以如果创建线程时没有指定线程名,那线程名就会是:
    Thread-0, Thread-1, Thread-2, Thread-3, …

    至此,我们看到,虽然Thread类的构造函数有这么多,但对我们来说真正重要的参数只有一个:

    Runnable target (Runnable 对象)

    所以创建一个线程实例最重要的是要传入一个Runnable类型对象。

    既然是Runnable类型,那么这个target必然是实现了Runnable接口的,也就是说该对象一定覆写了run方法。

    我们知道,Thread类本身也实现了Runnable接口,所以它必然也覆写了run方法,我们先来看看它的run方法:

    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
    

    可以看到,这个run方法仅仅是调用了target对象的run方法,如果我们在线程构造时没有传入target(例如调用了无参构造函数),那么这个run方法就什么也不会做。

    启动线程

    线程对象创建完了之后,接下来就是启动一个线程,在java中,启动一个线程必须调用线程的start方法:

    /**
     * Causes this thread to begin execution; the Java Virtual Machine
     * calls the <code>run</code> method of this thread.
     * <p>
     * The result is that two threads are running concurrently: the
     * current thread (which returns from the call to the
     * <code>start</code> method) and the other thread (which executes its
     * <code>run</code> method).
     * <p>
     * It is never legal to start a thread more than once.
     * In particular, a thread may not be restarted once it has completed
     * execution.
     *
     * @exception  IllegalThreadStateException  if the thread was already
     *               started.
     * @see        #run()
     * @see        #stop()
     */
    public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
    
        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);
    
        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }
    
    private native void start0()
    

    这个方法本质是调用了native的start0()方法,但是它的注释部分说明一些很重要的信息:

    这个方法使得线程开始执行,并由JVM来执行这个线程的run方法,结果就是有两个线程在并发执行,一个是当前线程,也就是调用了Thread#start方法的线程,另一个线程就是当前thread对象代表的线程,它执行了run方法。

    也就是说,这个Thread类实例代表的线程最终会执行它的run方法,而上面的分析中我们知道,它的run做的事就是调用Runnable对象的run方法,如果Runnable对象为null, 就啥也不做:

    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
    

    有的同学就要问了,绕了一大圈,忙了大半天,最后不就是为了执行target对象的run方法吗?为什么我们不直接调用target的run方法?这一层层的调用究竟是为了啥? 答案是:

    为了使用多线程 !

    我们知道,Thread类从定义上看就是个普通的java类,是什么魔法让它从一个普通的java类晋升为一个可以代表线程的类呢?是native方法!

    如果我们直接调用target对象的run方法,或者Thread类的run方法,那就是一个普通调用,因为run方法就是普普通通的类方法,与我们平时调用的其他类方法没有什么不同,这并不会产生多线程。

    但是,如果我们调用了start方法,由于它内部使用了native方法来启动线程,它将导致一个新的线程被创建出来, 而我们的Thread实例, 就代表了这个新创建出来的线程, 并且由这个新创建出来的线程来执行Thread实例的run方法。

    实战

    说了这么多理论的东西,下面让我们通过一个实战来加深理解。java官方文档给我们提供了两种创建线程的方法.

    方法1:继承Thread类,覆写run方法

    首先我们自定义一个继承自Thread的类,并覆写run方法:

    public class CustomizedThread extends Thread {
        public void run() {
            System.out.println("[" + Thread.currentThread().getName() + "线程]: " + "我是定义在CustomizedThread类中的run方法。");
        }
    }
    

    然后我们创建类的实例,并调用start方法启动这个线程:

    public class CustomizedThreadTest {
        public static void main(String[] args) {
            System.out.println("[" + Thread.currentThread().getName() + "线程]: " + "我在main方法里");
            CustomizedThread myThread = new CustomizedThread();
            myThread.start();
        }
    }
    

    执行结果:

    [main线程]: 我在main方法里
    [Thread-0线程]: 我是定义在CustomizedThread类中的run方法。
    

    可见,这里有两个线程,一个是main线程,它执行了main方法,一个是Thread-0线程,它是我们自定义的线程,它执行了run方法。

    如果我们不通过start方法来运行线程会有什么不同呢:

    public class CustomizedThreadTest {
        public static void main(String[] args) {
            System.out.println("[" + Thread.currentThread().getName() + "线程]: " + "我在main方法里");
            CustomizedThread myThread = new CustomizedThread();
            //myThread.start();
            myThread.run();
        }
    }
    

    这里我们直接调用自定义线程的run方法,看看结果有什么不同:

    [main线程]: 我在main方法里
    [main线程]: 我是定义在CustomizedThread类中的run方法。
    

    可见,这次只有一个main线程,由main线程执行了我们自定义线程类的run方法,并没有新的线程产生。 其实这个时候,CustomizedThread的run方法就是一个普普通通的类的普普通通的方法,与我们平时定义的方法并没有什么特别之处。

    有的同学要问了,上面不是说创建一个线程最重要的是传入一个Runnable对象吗? 我没有看到Runnable对象啊? 别急,我们来分析一下:

    首先,我们的CustomizedThread继承自Thread类,则我们会调用父类的无参构造函数:

    public Thread() {
        init(null, null, "Thread-" + nextThreadNum(), 0);
    }
    

    这个构造函数中,target对象为null;

    然后,我们使用了myThread.start(),因为我们在子类中没有定义start方法,所以,这个方法来自父类,而Thread类的start方法的作用我们已经讲过,它将新建一个线程,并调用它的run方法,这个新建的线程的抽象代表就是我们的CustomizedThread,所以它的(CustomizedThread的)run方法将会被调用。

    那么,如果我们的子类没有覆写run方法呢?,那自然是继承Thread类自己的run方法了:

    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
    

    而Thread类的run方法调用的又是target对象的run方法,而target对象现在为null, 所以这个方法啥也不做。

    所以到这里我们就很清晰了,创建一个线程最重要的是定义一个run方法,这个run方法要么通过继承Thread类的子类覆写,要么通过直接构造Thread类时传入一个Runnable的target对象。无论它由子类覆写提供还是由target对象提供,start方法最终都会新建一个线程来执行这个run方法。

    方法2:通过Runnable接口创建线程类

    我们先来看官方的例子:

    class PrimeRun implements Runnable {
         long minPrime;
         PrimeRun(long minPrime) {
             this.minPrime = minPrime;
         }
    
         public void run() {
             // compute primes larger than minPrime
              . . .
         }
    }
    //The following code would then create a thread and start it running:
    
    PrimeRun p = new PrimeRun(143);
    new Thread(p).start(); 
    

    这个例子中首先定义了一个PrimeRun类实现了Runnable接口,接着实例化出一个对象p,并将这个对象作为参数传递给Thread类的构造方法。

    这种方法看上去好像复杂了好多,但其实就是通过新建Thread类的对象来创建线程。它本质上就是传递一个Runnable对象给Thread的构造函数,所以我们完全可以用匿名类,又因为Runnable是一个函数接口,所以上面的代码完全可以被简写,我们来看一个例子:

    public class CustomizedThreadTest {
        public static void main(String[] args) {
            System.out.println("[" + Thread.currentThread().getName() + "线程]: " + "我在main方法里");
            Thread myThread = new Thread(() -> System.out.println("[" + Thread.currentThread().getName() + "线程]: " + "我是传递给Thread类的Runnable对象的run方法"));
            myThread.start();
        }
    }
    

    代码输出:

    [main线程]: 我在main方法里
    [Thread-0线程]: 我是传递给Thread类的Runnable对象的run方法
    

    这里,myThread是我们new出来的Thread类的实例,我们调用了Thread类的构造函数:

    public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }
    

    传入了一个Runnable对象,这个Runnable对象由lambda表达式表示。我们最后调用了 myThread.start()来启动这个线程,通过上一节的分析我们知道,start方法会调用run方法,而thread类的run方法最终会调用target对象的run方法,而target对象的run方法就是我们传进来的lambda表达式。上面这个例子其实等效于下面这种写法:

    public class CustomizedThreadTest {
        public static void main(String[] args) {
            System.out.println("[" + Thread.currentThread().getName() + "线程]: " + "我在main方法里");
            Thread myThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("[" + Thread.currentThread().getName() + "线程]: " + "我是传递给Thread类的Runnable对象的run方法");
                }
            });
            myThread.start();
        }
    }
    

    可见函数式接口和lambda表达式使我们的书写变得简洁多了。

    总结

    在java中,创建一个线程,有且仅有一种方式:

    创建一个Thread类实例,并调用它的start方法。

    创建一个Thread类的实例最重要的是定义一个run方法,这个run方法说明了这个线程具体要做什么事情。有两种方式定义一个run方法:

    • 继承Thread类,覆写run方法
    • 实现Runnale接口,将它作为target参数传递给Thread类构造函数

    启动一个线程一定要调用该线程的start方法,否则,并不会创建出新的线程来。

    展开全文
  • 启动线程的三种方式

    千次阅读 2021-01-01 07:41:29
    文章目录前言一、启动线程的第一种方法:继承类二、启动线程的第二种方式:实现接口三、启动线程的第三种方式:匿名内部类 前言 启动线程一共有三种方法:继承类,实现接口,匿名内部类。 一、启动线程的第一种...


    前言

    启动线程一共有三种方法:继承类,实现接口,匿名内部类。


    一、启动线程的第一种方法:继承Thread类

    start()方法的作用是启动一个分支线程,在JVM中开辟一个新的栈空间。
    只要新的栈空间,myThread.start()瞬间就结束了,线程就启动成功了。
    启动成功的线程会自动调用run方法,并且run方法在分支线的栈底部。

    代码如下(示例):

    public class Thread01  {
        public static void main(String[] args) {
            //创建线程对象
            MyThread myThread = new MyThread();
            //启动线程
            myThread.start();
    
            //主线程
            for (int i = 0; i <100 ; i++) {
                System.out.println("main主线程--->" + i);
            }
    
        }
    }
    class MyThread extends Thread{
        @Override
        public void run() {
            for (int i = 0; i <100 ; i++) {
                System.out.println("分支线程---->"+ i);
            }
        }
    }
    

    二、启动线程的第二种方式:实现Runnable接口

    代码如下(示例):

    public class Thread02 {
        public static void main(String[] args) {
            //创建线程对象
            Thread thread = new Thread(new MyRunnable());
            //启动线程
            thread.start();
    
            //主线程
            for (int i = 0; i <100 ; i++) {
                System.out.println("main主线程--->" + i);
            }
        }
    }
    class MyRunnable implements Runnable{
    
        @Override
        public void run() {
            for (int i = 0; i <100 ; i++) {
                System.out.println("分支线程---->"+ i);
            }
        }
    }
    

    实现接口启动线程是最常用的方法


    也可以使用匿名内部类的方式启动线程

    代码如下(示例):

    public class Thread03 {
        public static void main(String[] args) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i <1000 ; i++) {
                        System.out.println("分支线程-->" + i);
                    }
                }
            });
    
            //启动线程
            thread.start();
    
            //主线程
            for (int i = 0; i <1000 ; i++) {
                System.out.println("main主线程--->"+ i);
            }
        }
    }
    

    三、启动线程的第三种方式:实现Callable接口

    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    /***
     * 启动线程的第三种方法:实现Callable接口,重写call()方法
     */
    public class ThreadTest04 {
        public static void main(String[] args) {
            //创建一个“未来任务类”对象
            FutureTask futureTask = new FutureTask(new Callable() {
                @Override
                public Object call() throws Exception { //call()方法相当与run()方法,比run方法好,有返回值
                    System.out.println("call mothed begin!");
                    Thread.sleep(1000 * 10);
                    System.out.println("call mothed over!");
    
                    int x = 100;
                    int y = 200;
    
                    return x + y;//自动装箱
                }
            });
    
            //创建线程对象
            Thread t = new Thread(futureTask);
    
            //启动线程
            t.start();
    
            Object obj = null;
            //获得分支线程返回值
            try {
                //get()方法的执行会导致主线程的阻塞
                obj = futureTask.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
    
            System.out.println("获得分支线程的返回值:" + obj );
    
            //如下的代码会等到分支线程执行结束后,才回到主线程中继续执行
            System.out.println("Hello CSDN");
        }
    }
    
    
    展开全文
  • 易语言封装的启动线程是无法传递文本参数的,我们可以为这个要传递的文本申请一个内存地址,把这个地址传递过去,下面通过演示和封装来说明实现过程。 演示传递文本参数 1、创建一个文本型的变量,来存储要传递的...

    易语言封装的启动线程是无法传递文本参数的,我们可以为这个要传递的文本申请一个内存地址,把这个地址传递过去,下面通过演示和封装来说明实现过程。

    演示传递文本参数

    1、创建一个文本型的变量,来存储要传递的文本
    2、为这段文本申请内存,返回内存地址
    3、把文本参数写到内存
    4、启动线程,传递地址。
    5、启动的主线程的参数设置为文本型,接受传进来的文本

    511遇见(www.511yj.com) 

    .版本 2
    .支持库 spec
    .支持库 EThread
     
    .局部变量 文本参数, 文本型
    .局部变量 传递地址, 整数型
     
    文本参数 = “我是启动线程要传递的文本”
    传递地址 = 申请内存 (取文本长度 (文本参数) + 1, 真)
    写到内存 (到字节集 (文本参数), 传递地址, )
    启动线程 (&主线程, 传递地址, )
    

    主线程 

    511遇见(www.511yj.com) 

    .版本 2
     
    .子程序 主线程
    .参数 文本参数, 文本型
     
    输出调试文本 (文本参数)

    封装传递文本参数

    511遇见(www.511yj.com) 

    .版本 2
    .支持库 spec
    .支持库 EThread
     
    .子程序 启动线程_文本, 逻辑型
    .参数 子程序, 子程序指针
    .参数 文本参数, 文本型
    .局部变量 传递地址, 整数型
     
    传递地址 = 申请内存 (取文本长度 (文本参数) + 1, 真)
    写到内存 (到字节集 (文本参数), 传递地址, )
    返回 (启动线程 (子程序, 传递地址, ))

    调用启动线程_文本

    启动线程_文本 (&主线程, “我是启动线程要传递的文本”)

    文本和数组传递文本型参数的两种方法

    .版本 2 .支持库 EThread .支持库 spec  .程序集 窗口程序集1, , , 511遇见(www.511yj.com) .程序集变量 文本数组, 文本型, , "0"  .子程序 _按钮1_被单击, , , 511遇见(www.511yj.com) .局部变量 i, 整数型 .局部变量 变量, 文本型  .计次循环首 (100, i)     变量 = 到文本 (i)  ' 变量是文本型哦     启动线程 (&Thread1, 取变量数据地址 (变量))     延迟 (2)  ' 为了不出乱码 .计次循环尾 ()  .子程序 Thread, , , 511遇见(www.511yj.com) .参数 序号, 整数型  调试输出 (文本数组 [序号]) ' 数组间接传递  .子程序 Thread1, , , 511遇见(www.511yj.com) .参数 文本, 文本型  调试输出 (文本) ' 变量直接传递  .子程序 _按钮2_被单击, , , 511遇见(www.511yj.com) .局部变量 i, 整数型  .计次循环首 (100, i)     加入成员 (文本数组, 到文本 (i))     延时 (1)  ' 保持有效时间范围     启动线程 (&Thread, i) .计次循环尾 () 

    .版本 2
    .支持库 EThread
    .支持库 spec
    
    .程序集 窗口程序集1, , , 511遇见(www.511yj.com)
    .程序集变量 文本数组, 文本型, , "0"
    
    .子程序 _按钮1_被单击, , , 511遇见(www.511yj.com)
    .局部变量 i, 整数型
    .局部变量 变量, 文本型
    
    .计次循环首 (100, i)
        变量 = 到文本 (i)  ' 变量是文本型哦
        启动线程 (&Thread1, 取变量数据地址 (变量))
        延迟 (2)  ' 为了不出乱码
    .计次循环尾 ()
    
    .子程序 Thread, , , 511遇见(www.511yj.com)
    .参数 序号, 整数型
    
    调试输出 (文本数组 [序号])
    ' 数组间接传递
    
    .子程序 Thread1, , , 511遇见(www.511yj.com)
    .参数 文本, 文本型
    
    调试输出 (文本)
    ' 变量直接传递
    
    .子程序 _按钮2_被单击, , , 511遇见(www.511yj.com)
    .局部变量 i, 整数型
    
    .计次循环首 (100, i)
        加入成员 (文本数组, 到文本 (i))
        延时 (1)  ' 保持有效时间范围
        启动线程 (&Thread, i)
    .计次循环尾 ()
    
    

    源码:易语言启动线程传递文本参数

    展开全文
  • 易语言的启动线程默认是传递一个整数的,在易语言启动线程传递文本参数中,我们讲解了传递文本参数,今天,我们示范传递多个变量 思路是我们把要传递的变量定义成一个整数型数组,传递的是参数内容的内存地址指针,...
  • 线程池是如何启动线程

    千次阅读 2019-11-17 17:52:48
    啃完小龙虾掐指一算,周末又要结束了,赶紧来记录并分享点东西… … … 日常工作中多多少少都会需要用多线程去处理一些事情,下面就来记录并分享下线程池启动线程相关的知识: 一、线程池的好处 合理利用线程池会...
  • 线程传参自定义数据 • 1、自定义数据类型 • 2、传递自定义数据类型的指针 • 3、把数据内存指针转换为新数据内存指针 • 4、赋给新的自定义数据变量源码: .子程序 子程序1 .参数 a, 整数型 .局部变量 C, ...
  • Thread 和 启动线程几种方式

    千次阅读 2019-02-15 10:20:09
    启动线程几种方式第一种: 1】d定义Thread类的子类,并重写该类的run()方法,该方法的方法体就是线程需要完成的任务,run()方法也称为线程执行体。 2】创建Thread子类的实例,也就是创建了线程对象 3】启动线程,...
  • 易语言自动启动线程命令(),其实就是对API CreateThread的封装,我们如何启动线程的时候让它传递多个参数,并且类型可以是整数,是文本,在前面几个文章里,讲解了启动线程传参文本型,多个参数等等,今天我们用...
  • 自然地就想到在构造函数中启动线程,但是在陈硕《Linux多线程服务端编程》中提到,在构造函数中启动线程是不安全的,于是对这个问题进行了一番学习。 后来在...
  • 最近有小伙伴询问java怎么启动线程池?本篇来统一解答一下java启动线程的方法。 java怎么启动线程池? Java中创建线程有四种方式,我们下面依次介绍一下。 1、继承 Thread 类 (1)定义Thread类的子类,并重写该...
  • python 启动线程的两种方法

    千次阅读 2019-01-28 16:52:23
    Python调用线程有两种情况,一种是在主线程中直接调用,还一种是直接在其他方法中调用线程 在传递参数的方式上有所区别,两种调用方法如下: 1. 主进程中直接调用线程: from threading import Thread import ...
  • 首先Thread类中run()和start()方法的区别如下...start()方法:启动一个线程,调用该Runnable对象的run()方法,不能多次启动一个线程;public class Test implements Runnable{public static void main(String[] args...
  • 创建和启动线程的两种方式

    万次阅读 多人点赞 2016-10-07 10:52:48
    方式1:继承Thread类 步骤: 1):定义一个类A继承于java.lang.Thread类. 2):在A类中覆盖Thread类中的run方法. ...4):在main方法(线程)中,创建线程对象,并启动线程. (1)创建线程类对象: A类 a = new A类();
  • 子程序 _按钮_开始_被单击, , , 绑定,启动线程 .局部变量 n, 整数型 .局部变量 索引, 整数型 .局部变量 句柄, 整数型 .判断开始 (按钮_开始.标题 = “全部开始”) 按钮_开始.标题 = “全部停止” 超级延时 ...
  • java之内部类中启动线程

    千次阅读 2017-12-22 09:28:29
    2 如果想要在内部类中启动线程。并调用它。则和在方法体中启动一个线程差不多。不过该方法是内部类中的方法。传递的参数为list类型最好。 如:public class TestNeibuleiThread { public void test(){ ...
  • 多线程传参-数组传参 1、传递数组变量 2、取变量数据地址()... 启动线程 (&子程序1, 取变量数据地址 (文本数组 [n]), t) 等待线程 (t, 10) .计次循环尾 () .子程序 子程序1 .参数 a_address, 整数型 .局部...
  • 创建并启动线程几种方式

    千次阅读 2017-12-14 23:26:12
    一:创建线程的几种方式 1.第一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法,然后在run方法里填写相应的逻辑代码。class ThreadDemo1 extends Thread{ @Override public void run() {...
  • C++11启动线程的多种方式

    千次阅读 2017-10-02 15:16:28
    1、通过函数指针创建线程 #include #include using namespace std; void counter(int id,int numIterations) { for(int i=0;i;++i) { cout; } } int main() {
  • 线程启动会通过调用start方法来启动线程而不能直接调用run方法。 这里就会引出两个经典的面试题: 为什么线程启动是调用start方法来启动线程而不能直接调用run方法? 如果多次调用start方法会发生什么? 其实...
  • C++程序中启动线程的方法

    万次阅读 2017-11-13 09:33:43
    C++11 引入一个全新的线程库,包含启动和管理线程的工具,提供了同步(互斥、锁和原子变量)的方法,我将试图为你介绍这个全新的线程库。...启动线程 在 C++11 中启动一个线程是非常简单的,你可以使用 std:thr
  • 1、启动线程方式: 要启动的可以分为两类:返回结果和不返回结果。对于这两种,也分别有两种启动线程的方式: 1)继承Thread类,implements Runnable接口 2)实现Callable接口通过FutureTask包装器来创建Thread...
  • 多线程以及几种启动线程的方式

    千次阅读 2019-05-10 21:18:38
    线程进程和线程线程线程启动方式方式一方式二方式三方式四 进程和线程 进程和线程: 进程:正在执行的程序。 线程:一条独立的执行路径。 一个进程可以只有一条线程,也可以有多条线程。 多线程 Java中至少...
  • Thread使用start和run方法启动线程有什么区别?

    万次阅读 多人点赞 2018-04-14 12:35:05
    相信Thread对我们来说并不陌生,学java的时候都是入门的东西,我们一般使用thread都是new一个线程,然后调用start方法启动,使用start方法才真正实现了多线程运行,因为这个时候不用等待我们的run方法执行完成就可以...
  • 封装多线程模块-线程启动 • 1、CreateThread • 2、线程_启动_句柄() • 3、线程_启动_逻辑() • 4、线程句柄 • 5、线程ID • 6、易语言SHCreateThread 511遇见易语言多线程大漠多线程 SHCreateThread ...
  • Java启动线程两种方式总结

    千次阅读 2018-07-12 14:40:48
    先查看jdk帮助文档,这么进行描述线程线程是程序中的执行线程,可以由jvm来运行一个或者多个线程。 方法1:继承Thread 类 重写run方法即可 如下代码: public class Treadtest { //主方法 public static...
  • 怎样才是正确的线程启动方式?

    千次阅读 多人点赞 2022-05-31 10:11:39
    目录1、start()和run()的比较2、start()方法原理解读2.1、start()方法含义2.2、start()源码解析3、run()方法原理解读4、启动线程——常见面试问题 1、start()和run()的比较 代码演示: package threadcoreknowledge....
  • 易语言大漠多线程模板多线程启动

    千次阅读 2020-06-01 09:10:19
    线程启动主要是启动主线程,副线程启动放到主线程里,多线程启动就是把线程的句柄,线程PID,窗口句柄等,通过UI更新到窗口的超级列表框。 511遇见易语言多线程大漠多线程线程启动源码 .版本 2 .支持库 ...
  • java多线程之启动线程的三种方式

    万次阅读 多人点赞 2018-08-12 14:42:08
    java对多线程有着良好的支持,java创建和启动线程较为常用的方式有继承Thread类、实现Runnable接口和匿名内部类的方式。 1.继承Thread类: 通过继承Thread类来创建并启动多线程步骤如下: 1、定义Thread类的子类...
  • 内容 = “正在启动线程” + 到文本 (参数) 许可证1 = 创建进入许可证 () 进入许可区 (许可证1) .判断开始 (参数 = 1) 标签1.文本颜色 = #红色 标签1.标题 = “线程1已经启动” .循环判断首 () 程序_延时 (5000...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,099,768
精华内容 439,907
关键字:

如何启动线程