多线程基础知识(一) 线程的概念及创建任务与线程

线程的概念及创建任务与线程

引言

多线程使得程序中的多个任务可以同时执行。

java的重要功能之一就是内部支持多线程————在一个程序中运行同时运行多个任务。在许多程序设计语言中,多线程都是通过调用依赖于系统的过程或函数来实现的。在本文中,将介绍线程的该奶奶及如何在Java中运行一个多线程的例子。

一、线程的概念

概念

首先,何谓线程? 一个程序可能包含多个可以同时运行的任务,线程是指一个任务从头至尾的执行流程。

线程提供了运行一个任务的机制,对于Java而言,可以在一个程序中并发地启动多个线程,这些线程可以在多处理器系统上同时运行。若只有一个处理器,则多个线程共享单个CPU。

在单处理器系统中,多个线程共享CPU时间成为时间分享,而操作系统负责调度及分配资源给它们。这种安排之所以是可行的,是因为CPU的大部分时间都是空闲的。例如,在等待用户输入数据时,CPU什么都不做。

多线程可以使程序反应更快、交互性更强、执行效率更高,例如,一个好的文字处理程序允许在输入文字的同时打印或者保存文件。在一些情况下,即使是在单处理器系统上,多线程程序的运行速度也比单线程程序更快。Java对多线程程序的创建和运行,以及锁定资源以避免冲突提供了非常好的支持。

Java中的线程

可以在程序中创建附加的线程以执行并发任务在Java中,每个任务都是Runnable接口的一个实例,也称为可运行对象(runnable object)

Java中,从本质上来讲,线程就是一个便于任务执行的对象

二、如何创建任务与线程

如上一小节中所讲,任务就是对象。为了创建任务,必须首先为这个任务定义一个实现Runnable接口的类(否则如何创建这个实例呢?)。Runnable接口非常简单,它只包含一个run方法,因此只要我们创建的类中也包含这个方法即可。而这个方法的作用就是告诉系统线程将如何运行的。如我们可以如以下的形式定义一个实现某任务的类:

public class TaskClass implements runnable {
  public TaskClass(...) {}
  @Override
  public void run()
}

人任务必须在线程中执行,Thread类包括创建线程的构造方法以及控制线程的很多有用的方法,如对于上面的TaskClass类,可以使用如下的语句为其创建任务的线程:

  TaskClass task = new TaskClass(...);  // 先创建一个任务的实例
  Thread thread = new Thread(task);     // 将可运行对象传入

然后调用start()方法告诉Java虚拟机该线程准备运行:

  thread.start()

之后,Java虚拟机通过调用任务的run()方法执行任务。

在下面的例子中,会创建3个任务以及3个运行这些任务的线程,其中:

  • 任务1 打印字母 ‘a’ 100次
  • 任务2 打印从1到100的整数

首先,是创建两个分别实现这两个任务的类:

// PrintChar.java

package learning_java.book.concurrency;

public class PrintChar implements Runnable {
    private char charToPrint;
    private int times;

    public PrintChar(char c, int t) {
        charToPrint = c;
        times = t;
    }

    @Override
    public void run() {
        for (int i = 0; i < times; i ++) {
            System.out.print(charToPrint);
        }
    }
}
// PrintNum.java

package learning_java.book.concurrency;

public class PrintNum implements Runnable{
    private int lastNum;

    public PrintNum(int n) {
        lastNum = n;
    }

    public void run() {
        for (int i = 1; i <= lastNum; i ++) {
            System.out.print(" " + i);
        }
    }

    public static void main(String[] args) {
        new PrintNum(10).run();
    }
}

之后,再创建一个主方法的类,创建这两个任务的实例,并为其创建线程并运行。

//TaskThreadDemo.java

package learning_java.book.concurrency;

public class TaskThreadDemo {
    public static void main(String[] args) {
        Runnable printA = new PrintChar('a', 100);
        Runnable print100 = new PrintNum(100);

        Thread thread1 = new Thread(printA);
        Thread thread2 = new Thread(print100);

        thread1.start();
        thread2.start();
    }
}

输出:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 1aaaaaaaaaaa 2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 3a 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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

在这短程序中,若从结果看不到并发运行三个线程的效果,那么就要增加打印字符与数字的个数,如更改为打印1000次。

最后,还有一点需要注意的是,在任务类中的run()方法知名如何完成这个任务,如果使用Thread类的方法为其构建线程并运行的话,Java虚拟机会自动调用该方法,而无需特意调用它。如果手动在代码中调用一个实例的run()方法,则效果只是在同一个线程中执行该方法,而不是有新线程被启动。

猜你喜欢

转载自blog.csdn.net/lenfranky/article/details/85546033