`
IXHONG
  • 浏览: 450471 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

如何创建线程

阅读更多

在前面,已经介绍了Java的基础知识,现在我们来讨论一点稍微难一点的问题:Java并发编程。当然,Java并发编程涉及到很多方面的内容,不是一朝一夕就能够融会贯通使用的,需要在实践中不断积累。由于并发肯定涉及到多线程,因此在进入并发编程主题之前,我们先来了解一下进程和线程的由来,这对后面对并发编程的理解将会有很大的帮助。

  下面是本文的目录大纲:

  一.操作系统中为什么会出现进程?

  二.为什么会出现线程?

  三.多线程并发

  若有不正之处,请多多谅解并欢迎指正。

  请尊重作者劳动成果,转载请标明原文地址:

  http://www.cnblogs.com/dolphin0520/p/3910667.html

一.操作系统中为什么会出现进程?

  说起进程的由来,我们需要从操作系统的发展历史谈起。

  也许在今天,我们无法想象在很多年以前计算机是什么样子。我们现在可以用计算机来做很多事情:办公、娱乐、上网,但是在计算机刚出现的时候,是为了解决数学计算的问题,因为很多大量的计算通过人力去完成是很耗时间和人力成本的。在最初的时候,计算机只能接受一些特定的指令,用户输入一个指令,计算机就做一个操作。当用户在思考或者输入数据时,计算机就在等待。显然这样效率和很低下,因为很多时候,计算机处于等待用户输入的状态。

  那么能不能把一系列需要操作的指令预先写下来,形成一个清单,然后一次性交给计算机,计算机不断地去读取指令来进行相应的操作?就这样,批处理操作系统诞生了。用户可以将需要执行的多个程序写在磁带上,然后交由计算机去读取并逐个地执行这些程序,并将输出结果写到另一个磁带上。

  虽然批处理操作系统的诞生极大地提高了任务处理的便捷性,但是仍然存在一个很大的问题:

  假如有两个任务A和B,任务A在执行到一半的过程中,需要读取大量的数据输入(I/O操作),而此时CPU只能静静地等待任务A读取完数据才能继续执行,这样就白白浪费了CPU资源。人们于是想,能否在任务A读取数据的过程中,让任务B去执行,当任务A读取完数据之后,让任务B暂停,然后让任务A继续执行?

  但是这样就有一个问题,原来每次都是一个程序在计算机里面运行,也就说内存中始终只有一个程序的运行数据。而如果想要任务A执行I/O操作的时候,让任务B去执行,必然内存中要装入多个程序,那么如何处理呢?多个程序使用的数据如何进行辨别呢?并且当一个程序运行暂停后,后面如何恢复到它之前执行的状态呢?

  这个时候人们就发明了进程,用进程来对应一个程序,每个进程对应一定的内存地址空间,并且只能使用它自己的内存空间,各个进程间互不干扰。并且进程保存了程序每个时刻的运行状态,这样就为进程切换提供了可能。当进程暂时时,它会保存当前进程的状态(比如进程标识、进程的使用的资源等),在下一次重新切换回来时,便根据之前保存的状态进行恢复,然后继续执行。

  这就是并发,能够让操作系统从宏观上看起来同一个时间段有多个任务在执行。换句话说,进程让操作系统的并发成为了可能。

  注意,虽然并发从宏观上看有多个任务在执行,但是事实上,任一个具体的时刻,只有一个任务在占用CPU资源(当然是对于单核CPU来说的)。

二.为什么会出现线程?

  在出现了进程之后,操作系统的性能得到了大大的提升。虽然进程的出现解决了操作系统的并发问题,但是人们仍然不满足,人们逐渐对实时性有了要求。因为一个进程在一个时间段内只能做一件事情,如果一个进程有多个子任务,只能逐个地去执行这些子任务。比如对于一个监控系统来说,它不仅要把图像数据显示在画面上,还要与服务端进行通信获取图像数据,还要处理人们的交互操作。如果某一个时刻该系统正在与服务器通信获取图像数据,而用户又在监控系统上点击了某个按钮,那么该系统就要等待获取完图像数据之后才能处理用户的操作,如果获取图像数据需要耗费10s,那么用户就只有一直在等待。显然,对于这样的系统,人们是无法满足的。

  那么可不可以将这些子任务分开执行呢?即在系统获取图像数据的同时,如果用户点击了某个按钮,则会暂停获取图像数据,而先去响应用户的操作(因为用户的操作往往执行时间很短),在处理完用户操作之后,再继续获取图像数据。人们就发明了线程,让一个线程去执行一个子任务,这样一个进程就包括了多个线程,每个线程负责一个独立的子任务,这样在用户点击按钮的时候,就可以暂停获取图像数据的线程,让UI线程响应用户的操作,响应完之后再切换回来,让获取图像的线程得到CPU资源。从而让用户感觉系统是同时在做多件事情的,满足了用户对实时性的要求。

  换句话说,进程让操作系统的并发性成为可能,而线程让进程的内部并发成为可能。

  但是要注意,一个进程虽然包括多个线程,但是这些线程是共同享有进程占有的资源和地址空间的。进程是操作系统进行资源分配的基本单位,而线程是操作系统进行调度的基本单位。

三.多线程并发

  由于多个线程是共同占有所属进程的资源和地址空间的,那么就会存在一个问题:

  如果多个线程要同时访问某个资源,怎么处理?

  这个问题就是后序文章中要重点讲述的同步问题。

  那么可能有朋友会问,现在很多时候都采用多线程编程,那么是不是多线程的性能一定就由于单线程呢?

  不一定,要看具体的任务以及计算机的配置。比如说:

  对于单核CPU,如果是CPU密集型任务,如解压文件,多线程的性能反而不如单线程性能,因为解压文件需要一直占用CPU资源,如果采用多线程,线程切换导致的开销反而会让性能下降。

  但是对于比如交互类型的任务,肯定是需要使用多线程的、

  而对于多核CPU,对于解压文件来说,多线程肯定优于单线程,因为多个线程能够更加充分利用每个核的资源。

  虽然多线程能够提升程序性能,但是相对于单线程来说,它的编程要复杂地多,要考虑线程安全问题。因此,在实际编程过程中,要根据实际情况具体选择。

  关于进程和线程的由来,暂时就讲这么多了,感兴趣的朋友可以参考相关资料。

-----------------------------------------------------------------------------------------------------------

在前面一篇文章中已经讲述了在进程和线程的由来,今天就来讲一下在Java中如何创建线程,让线程去执行一个子任务。下面先讲述一下Java中的应用程序和进程相关的概念知识,然后再阐述如何创建线程以及如何创建进程。下面是本文的目录大纲:

  一.Java中关于应用程序和进程相关的概念

  二.Java中如何创建线程

  三.Java中如何创建进程

  若有不正之处,请多多谅解并欢迎批评指正。

  请尊重作者劳动成果,转载请标明原文链接:

   http://www.cnblogs.com/dolphin0520/p/3913517.html

一.Java中关于应用程序和进程相关的概念

  在Java中,一个应用程序对应着一个JVM实例(也有地方称为JVM进程),一般来说名字默认为java.exe或者javaw.exe(windows下可以通过任务管理器查看)。Java采用的是单线程编程模型,即在我们自己的程序中如果没有主动创建线程的话,只会创建一个线程,通常称为主线程。但是要注意,虽然只有一个线程来执行任务,不代表JVM中只有一个线程,JVM实例在创建的时候,同时会创建很多其他的线程(比如垃圾收集器线程)。

  由于Java采用的是单线程编程模型,因此在进行UI编程时要注意将耗时的操作放在子线程中进行,以避免阻塞主线程(在UI编程时,主线程即UI线程,用来处理用户的交互事件)。

二.Java中如何创建线程

  在java中如果要创建线程的话,一般有两种方式:1)继承Thread类;2)实现Runnable接口。

  1.继承Thread类

  继承Thread类的话,必须重写run方法,在run方法中定义需要执行的任务。

1
2
3
4
5
6
7
8
9
10
11
12
class MyThread extends Thread{
    private static int num = 0;
     
    public MyThread(){
        num++;
    }
     
    @Override
    public void run() {
        System.out.println("主动创建的第"+num+"个线程");
    }
}

   创建好了自己的线程类之后,就可以创建线程对象了,然后通过start()方法去启动线程。注意,不是调用run()方法启动线程,run方法中只是定义需要执行的任务,如果调用run方法,即相当于在主线程中执行run方法,跟普通的方法调用没有任何区别,此时并不会创建一个新的线程来执行定义的任务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Test {
    public static void main(String[] args)  {
        MyThread thread = new MyThread();
        thread.start();
    }
}
 
 
class MyThread extends Thread{
    private static int num = 0;
     
    public MyThread(){
        num++;
    }
     
    @Override
    public void run() {
        System.out.println("主动创建的第"+num+"个线程");
    }
}

   在上面代码中,通过调用start()方法,就会创建一个新的线程了。为了分清start()方法调用和run()方法调用的区别,请看下面一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Test {
    public static void main(String[] args)  {
        System.out.println("主线程ID:"+Thread.currentThread().getId());
        MyThread thread1 = new MyThread("thread1");
        thread1.start();
        MyThread thread2 = new MyThread("thread2");
        thread2.run();
    }
}
 
 
class MyThread extends Thread{
    private String name;
     
    public MyThread(String name){
        this.name = name;
    }
     
    @Override
    public void run() {
        System.out.println("name:"+name+" 子线程ID:"+Thread.currentThread().getId());
    }
}

   运行结果:

  从输出结果可以得出以下结论:

  1)thread1和thread2的线程ID不同,thread2和主线程ID相同,说明通过run方法调用并不会创建新的线程,而是在主线程中直接运行run方法,跟普通的方法调用没有任何区别;

  2)虽然thread1的start方法调用在thread2的run方法前面调用,但是先输出的是thread2的run方法调用的相关信息,说明新线程创建的过程不会阻塞主线程的后续执行。

  2.实现Runnable接口

  在Java中创建线程除了继承Thread类之外,还可以通过实现Runnable接口来实现类似的功能。实现Runnable接口必须重写其run方法。

下面是一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Test {
    public static void main(String[] args)  {
        System.out.println("主线程ID:"+Thread.currentThread().getId());
        MyRunnable runnable = new MyRunnable();
        Thread thread = new Thread(runnable);
        thread.start();
    }
}
 
 
class MyRunnable implements Runnable{
     
    public MyRunnable() {
         
    }
     
    @Override
    public void run() {
        System.out.println("子线程ID:"+Thread.currentThread().getId());
    }
}

   Runnable的中文意思是“任务”,顾名思义,通过实现Runnable接口,我们定义了一个子任务,然后将子任务交由Thread去执行。注意,这种方式必须将Runnable作为Thread类的参数,然后通过Thread的start方法来创建一个新线程来执行该子任务。如果调用Runnable的run方法的话,是不会创建新线程的,这根普通的方法调用没有任何区别。

  事实上,查看Thread类的实现源代码会发现Thread类是实现了Runnable接口的。

  在Java中,这2种方式都可以用来创建线程去执行子任务,具体选择哪一种方式要看自己的需求。直接继承Thread类的话,可能比实现Runnable接口看起来更加简洁,但是由于Java只允许单继承,所以如果自定义类需要继承其他类,则只能选择实现Runnable接口。

三.Java中如何创建进程

   在Java中,可以通过两种方式来创建进程,总共涉及到5个主要的类。

  第一种方式是通过Runtime.exec()方法来创建一个进程,第二种方法是通过ProcessBuilder的start方法来创建进程。下面就来讲一讲这2种方式的区别和联系。

  首先要讲的是Process类,Process类是一个抽象类,在它里面主要有几个抽象的方法,这个可以通过查看Process类的源代码得知:

  位于java.lang.Process路径下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public abstract class Process
{
    
    abstract public OutputStream getOutputStream();   //获取进程的输出流
      
    abstract public InputStream getInputStream();    //获取进程的输入流
 
    abstract public InputStream getErrorStream();   //获取进程的错误流
 
    abstract public int waitFor() throws InterruptedException;   //让进程等待
  
    abstract public int exitValue();   //获取进程的退出标志
 
    abstract public void destroy();   //摧毁进程
}

  1)通过ProcessBuilder创建进程

  ProcessBuilder是一个final类,它有两个构造器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public final class ProcessBuilder
{
    private List<String> command;
    private File directory;
    private Map<String,String> environment;
    private boolean redirectErrorStream;
 
    public ProcessBuilder(List<String> command) {
    if (command == null)
        throw new NullPointerException();
    this.command = command;
    }
 
    public ProcessBuilder(String... command) {
    this.command = new ArrayList<String>(command.length);
    for (String arg : command)
        this.command.add(arg);
    }
....
}

   构造器中传递的是需要创建的进程的命令参数,第一个构造器是将命令参数放进List当中传进去,第二构造器是以不定长字符串的形式传进去。

  那么我们接着往下看,前面提到是通过ProcessBuilder的start方法来创建一个新进程的,我们看一下start方法中具体做了哪些事情。下面是start方法的具体实现源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public Process start() throws IOException {
// Must convert to array first -- a malicious user-supplied
// list might try to circumvent the security check.
String[] cmdarray = command.toArray(new String[command.size()]);
for (String arg : cmdarray)
    if (arg == null)
    throw new NullPointerException();
// Throws IndexOutOfBoundsException if command is empty
String prog = cmdarray[0];
 
SecurityManager security = System.getSecurityManager();
if (security != null)
    security.checkExec(prog);
 
String dir = directory == null null : directory.toString();
 
try {
    return ProcessImpl.start(cmdarray,
                 environment,
                 dir,
                 redirectErrorStream);
catch (IOException e) {
    // It's much easier for us to create a high-quality error
    // message than the low-level C code which found the problem.
    throw new IOException(
    "Cannot run program \"" + prog + "\""
    + (dir == null "" " (in directory \"" + dir + "\")")
    ": " + e.getMessage(),
    e);
}
}

   该方法返回一个Process对象,该方法的前面部分相当于是根据命令参数以及设置的工作目录进行一些参数设定,最重要的是try语句块里面的一句:

1
2
3
4
return ProcessImpl.start(cmdarray,
                    environment,
                    dir,
                    redirectErrorStream);

   说明真正创建进程的是这一句,注意调用的是ProcessImpl类的start方法,此处可以知道start必然是一个静态方法。那么ProcessImpl又是什么类呢?该类同样位于java.lang.ProcessImpl路径下,看一下该类的具体实现:

  ProcessImpl也是一个final类,它继承了Process类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
final class ProcessImpl extends Process {
 
    // System-dependent portion of ProcessBuilder.start()
    static Process start(String cmdarray[],
             java.util.Map<String,String> environment,
             String dir,
             boolean redirectErrorStream)
    throws IOException
    {
    String envblock = ProcessEnvironment.toEnvironmentBlock(environment);
    return new ProcessImpl(cmdarray, envblock, dir, redirectErrorStream);
    }
 ....
}

   这是ProcessImpl类的start方法的具体实现,而事实上start方法中是通过这句来创建一个ProcessImpl对象的:

1
return new ProcessImpl(cmdarray, envblock, dir, redirectErrorStream);

   而在ProcessImpl中对Process类中的几个抽象方法进行了具体实现。

  说明事实上通过ProcessBuilder的start方法创建的是一个ProcessImpl对象。

  下面看一下具体使用ProcessBuilder创建进程的例子,比如我要通过ProcessBuilder来启动一个进程打开cmd,并获取ip地址信息,那么可以这么写:

1
2
3
4
5
6
7
8
9
10
11
12
public class Test {
    public static void main(String[] args) throws IOException  {
        ProcessBuilder pb = new ProcessBuilder("cmd","/c","ipconfig/all");
        Process process = pb.start();
        Scanner scanner = new Scanner(process.getInputStream());
         
        while(scanner.hasNextLine()){
            System.out.println(scanner.nextLine());
        }
        scanner.close();
    }
}

   第一步是最关键的,就是将命令字符串传给ProcessBuilder的构造器,一般来说,是把字符串中的每个独立的命令作为一个单独的参数,不过也可以按照顺序放入List中传进去。

  至于其他很多具体的用法不在此进行赘述,比如通过ProcessBuilder的environment方法和directory(File directory)设置进程的环境变量以及工作目录等,感兴趣的朋友可以查看相关API文档。

  2)通过Runtime的exec方法来创建进程

  首先还是来看一下Runtime类和exec方法的具体实现,Runtime,顾名思义,即运行时,表示当前进程所在的虚拟机实例。

  由于任何进程只会运行于一个虚拟机实例当中,所以在Runtime中采用了单例模式,即只会产生一个虚拟机实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Runtime {
    private static Runtime currentRuntime = new Runtime();
 
    /**
     * Returns the runtime object associated with the current Java application.
     * Most of the methods of class <code>Runtime</code> are instance
     * methods and must be invoked with respect to the current runtime object.
     *
     * @return  the <code>Runtime</code> object associated with the current
     *          Java application.
     */
    public static Runtime getRuntime() {
    return currentRuntime;
    }
 
    /** Don't let anyone else instantiate this class */
    private Runtime() {}
    ...
 }

   从这里可以看出,由于Runtime类的构造器是private的,所以只有通过getRuntime去获取Runtime的实例。接下来着重看一下exec方法 实现,在Runtime中有多个exec的不同重载实现,但真正最后执行的是这个版本的exec方法:

1
2
3
4
5
6
7
public Process exec(String[] cmdarray, String[] envp, File dir)
   throws IOException {
   return new ProcessBuilder(cmdarray)
       .environment(envp)
       .directory(dir)
       .start();
   }

   可以发现,事实上通过Runtime类的exec创建进程的话,最终还是通过ProcessBuilder类的start方法来创建的。

  下面看一个例子,看一下通过Runtime的exec如何创建进程,还是前面的例子,调用cmd,获取ip地址信息:

1
2
3
4
5
6
7
8
9
10
11
12
public class Test {
    public static void main(String[] args) throws IOException  {
        String cmd = "cmd "+"/c "+"ipconfig/all";
        Process process = Runtime.getRuntime().exec(cmd);
        Scanner scanner = new Scanner(process.getInputStream());
         
        while(scanner.hasNextLine()){
            System.out.println(scanner.nextLine());
        }
        scanner.close();
    }
}

   要注意的是,exec方法不支持不定长参数(ProcessBuilder是支持不定长参数的),所以必须先把命令参数拼接好再传进去。

  关于在Java中如何创建线程和进程的话,暂时就讲这么多了,感兴趣的朋友可以参考相关资料、

  参考资料:

  http://luckykapok918.blog.163.com/blog/static/205865043201210272168556/

  http://www.cnblogs.com/ChrisWang/archive/2009/12/02/use-java-lang-process-and-processbuilder-to-create-native-application-process.html

  http://lavasoft.blog.51cto.com/62575/15662/

  《Java编程思想》

   

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

相关推荐

    Java使用Callable和Future创建线程操作示例

    "Java使用Callable和Future创建线程操作示例" Java使用Callable和Future创建线程操作示例主要介绍了Java使用Callable和Future创建线程操作,结合实例形式分析了java使用Callable接口和Future类创建线程的相关操作...

    创建线程,利用互斥实现线程共享变量通信

    一、题目: 创建线程,利用互斥实现线程共享变量通信 二、目的 掌握线程创建和终止,加深对线程和进程概念的理解,会用同步与互斥方法实现线程之间的通信。 三、内容和要求 软件界面上点“创建线程” 按钮,创建三个...

    VB创建线程动态链接库(VBCreateThread.dll)

    功能:VB创建线程(其它语言没测试过,不知是否能用)。 编写原因:鉴于VB创建稳定线程的需求 特点:可替代API CreateThread来创建线程,且自动对线程进行初始化,线程函数中不再需要初始化线程就可以使用对象、类、...

    在Java中创建线程有两种方法

    在Java编程语言中,创建线程是实现并发执行任务的关键步骤。Java提供了两种主要的方法来创建线程,分别是直接继承自`Thread`类和实现`Runnable`接口。这两种方法各有其特点和适用场景。 1. **继承Thread类**: 当...

    VS2008 C# 创建线程,根据按钮可以控制线程的运行情况。

    本教程将详细介绍如何在VS2008中创建线程,并通过按钮来控制线程的运行状态。 首先,我们需要了解C#中的线程类`System.Threading.Thread`。这个类提供了创建新线程的方法,如`new Thread(new ThreadStart...

    创建线程 示例 vc++

    在VC++环境中,创建线程是一项重要的多任务处理技术,特别是在开发实时系统、网络编程以及高性能应用程序时。本文将深入探讨如何在VC++中创建线程,并基于《vc++网络编程经典案例》一书中的示例进行讲解。 线程是...

    创建线程的源代码资源

    本资源主要关注如何在不同的编程语言中创建线程,以下是对创建线程这一主题的详细阐述。 在Java中,创建线程有以下两种方法: 1. 继承Thread类:创建一个新的类,该类继承自`java.lang.Thread`,然后重写`run()`...

    创建线程及线程间通信

    本话题将深入探讨如何创建线程以及线程间如何进行通信,特别是通过互斥信号量实现线程的互斥访问。 首先,我们要理解什么是线程。线程是操作系统分配处理器时间的基本单位,它是进程内的执行单元。在同一个进程中,...

    分离状态创建线程

    可结合线程是默认状态,意味着在创建线程后,父线程需要通过调用`pthread_join()`函数来等待新线程的结束,以便回收资源和获取线程的返回值。在这个过程中,新线程的内存资源(如栈空间)不会被释放,直到父线程调用...

    Qt创建线程的两种方式+线程池方式

    1.方式1:继承 QThread 类方式:通过继承 QThread 类并重写 run() 函数来创建线程,线程对象本身即为线程。 优点:相对简单,易于理解和实现;可以直接重写 run() 函数来定义线程的逻辑;可以通过信号和槽机制与其他...

    易语言类方法创建线程

    易语言类方法创建线程源码,类方法创建线程,ddd,取当前类指针,取方法指针,创建线程,线程接口,创建循环线程,关闭循环线程,取循环线程空闲索引,循环线程接口,线程_创建线程,线程_等待执行完毕,线程_线程结束,操作_取...

    window平台下创建线程程序

    window平台下创建线程程序,已经跑通 线程1和线程2

    C# 创建线程 控制和查看线程的运行情况

    C# 创建线程 控制和查看线程的运行情况 京华志&精华志出品 希望大家互相学习,互相进步 支持CSDN 支持微软 主要包括C# ASP.NET SQLDBA 源码 毕业设计 开题报告 答辩PPT等

    C++创建线程C++创建线程

    创建线程是实现多线程编程的关键步骤。本篇文章将详细探讨C++中如何创建线程,以及相关知识点。 1. **线程库的选择** 在C++11及以后的版本中,标准库提供了`&lt;thread&gt;`头文件,支持了原生的线程创建。除此之外,还...

    C#创建线程

    本文将深入探讨C#中如何创建线程、多线程更新界面、使用委托以及跨线程调用控件的相关知识。 ### 创建线程 在C#中,创建线程主要通过以下两种方式: 1. **System.Threading.Thread** 类:这是最基础的创建线程的...

    创建线程类轻松实现线程管理

    Java作为多线程编程的强大语言,提供了多种创建线程的方法,其中一种是通过创建线程类来实现。本文将深入探讨如何创建线程类以及如何进行线程管理,帮助你轻松掌握这一核心技能。 首先,我们来看看如何在Java中创建...

    java中创建线程两个方法及区别

    Java提供了多种创建线程的方式,其中最常见的是通过继承`Thread`类和实现`Runnable`接口这两种方法。下面将详细阐述这两种创建线程的方法及其区别。 ### 一、通过继承`Thread`类创建线程 当一个类继承了`Thread`类...

    java tcp server 创建线程监听端口,创建线程处理连接

    这个文件可能定义了一个`TcpServerThread`类,该类包含创建`ServerSocket`、监听端口、处理新连接并创建线程的逻辑。通过阅读和理解这个源代码,你可以更深入地学习如何在Java中实现多线程TCP服务器。 总之,Java ...

    java多线程代码案例(创建线程,主线程,线程优先级,线程组,线程同步,线程间的通信)

    本文将深入探讨Java多线程中的关键知识点,包括创建线程、主线程、线程优先级、线程组、线程同步以及线程间的通信。 1. **创建线程** 在Java中,可以通过两种方式创建线程:继承`Thread`类或实现`Runnable`接口。...

    MFC创建多线程(工作者线程)demo

    `AfxBeginThread`是MFC提供的一个方便的函数,用于创建线程。它的主要优点在于能自动管理线程的资源,比如清理消息队列、调用`_AFXWIN_INIT`来初始化MFC支持,以及在线程结束时调用`AfxEndThread`。这些都是MFC程序...

Global site tag (gtag.js) - Google Analytics