面试天坑_002_线程与多线程

/*
线程的定义

线程是进程内一个相对独立的、可调度的执行单元。

在一个进程内部可以有多个线程,即有多个执行流,这多个线程是共享进程的内存空间和系统资源。

它们轮换使用这块内存空间。

多线程是为了使得多个线程并行的工作以完成多项任务,以提高系统的效率。
*/

可知线程有以下性质:

(1) 线程是进程内的一个相对独立的可执行单元。

(2) 线程是操作系统中的基本调度单元,因此线程中应包含有调度所需的必要信息。

(3) 由于线程是被调度的基本单元,而进程不是调度的单元。所以每个进程在创建时,至少需要同时为该进程创建一个线程。也就是说进程中至少要有一个或一个以上线程,否则该进程无法被调度执行。

(4) 需要时,线程可以创建其他线程。

(5) 进程是被分给并拥有资源的基本单元,同一进程内的多个线程共享该进程的资源。但线程并不拥有资源,只是使用它们。

(6) 由于共享资源(包括数据和文件),所以线程间需要通信和同步机制。

(7) 线程有生命期,有诞生和死亡。在生命期中有状态的变化。

 

使用多进程和多线程的优点

多进程的优点:在同一个时间里,同一个计算机系统中如果允许两个或两个以上的进程处于运行状态,这便是多任务。

现代的操作系统几乎都是多任务操作系统,能够同时管理多个进程的运行。

多任务带来的好处是明显的,比如你可以边听mp3边上网,与此同时甚至可以将下载的文档打印出来,而这些任务之间丝毫不会相互干扰。

那么这里就涉及到并行的问题,俗话说,一心不能二用,这对计算机也一样,原则上一个CPU只能分配给一个进程,以便运行这个进程。

我们通常使用的计算机中只有一个CPU,也就是说只有一颗心,要让它一心多用,同时运行多个进程,就必须使用并发技术。

实现并发技术相当复杂,最容易理解的是“时间片轮转进程调度算法”,

它的思想简单介绍如下:

  在操作系统的管理下,所有正在运行的进程轮流使用CPU,每个进程允许占用CPU的时间非常短(比如10毫秒),这样用户根本感觉不出来CPU是在轮流为多个进程服务,就好象所有的进程都在不间断地运行一样。但实际上在任何一个时间内有且仅有一个进程占有CPU。

 

多线程的优点:多线程程序作为一种多任务、并发的工作方式,有以下的优点:

(1) 提高应用程序响应。这对图形界面的程序尤其有意义,当一个操作耗时很长时,整个系统都会等待这个操作,此时程序不会响应键盘、鼠标、菜单的操作,而使用多线程技术,将耗时长的操作(time consuming)置于一个新的线程,可以避免这种尴尬的情况。

(2) 使多CPU系统更加有效。操作系统会保证当线程数不大于CPU数目时,不同的线程运行于不同的CPU上。

(3) 改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序会利于理解和修改。

/******************************************************************************************************/

Java语言中有一个重要的特性是支持多线程,

在Java中,一个应用程序可以包含多个线程。

每个线程执行特定的任务,并可与其他线程并发执行;

多线程使系统的空转时间最少,提高CPU利用率;

多线程编程环境用方便的模型隐藏CPU在任务间切换的事实。

 

在Java程序启动时,一个线程立刻运行,该线程通常称为程序的主线程。

 

主线程的重要性体现在两个方面:

它是产生其他子线程的线程。

通常它必须最后完成执行,因为它执行各种关闭动作。

 1 package Process.Thread;
 2 
 3 public class MainThread {
 4     public static void main(String[] args) {
 5         Thread test = new Thread();
 6         System.out.println("修改前线程为" + test);
 7         for (int i = 1; i < 4; i++) {
 8             System.out.println(i);
 9             try {
10                 Thread.sleep(3000);
11             } catch (InterruptedException e) {
12                 // TODO Auto-generated catch block
13                 System.out.println("线程被中断!!!");
14                 e.printStackTrace();
15             }
16         }
17         test.setName("JavaThreadTest_By_ZW");
18         System.out.println("修改后线程为" + test);
19 
20     }
21 }

输出情况为

 

 

开始运行的时候只是出现

修改前线程为Thread[Thread-0,5,main]
1

[三秒后输出]
2

[三秒后输出]

3

[三秒后输出]
修改后线程为Thread[JavaThreadTest_By_ZW,5,main]

解析:

第一个输出:获得当前线程,即主线程

中间间隔时间:输出每个数后暂停3000毫秒

最后输出:改变线程的内部名称后的主线程

/******************************************************************************************************/

/*
线程的创建一:
声明一个 Thread 类的子类,并覆盖 run() 方法。 
*/
package Process.Thread;

public class CreateThread {
public static void main(String[] args) {
    CustomThread t = new CustomThread();
    System.out.println(t);
    t.run();
}
}

class CustomThread extends Thread {
    public void run() {
    // 覆盖该方法 
    System.out.println("覆盖以前的方法");
    }
}

 

/*
线程的创建一:
声明一个实现 Runnable 接口的类,并实现 run() 方法
(注:此种做法只实现的线程任务)。 

*/
package Process.Thread;

public class CreateRunnable {
    public static void main(String[] args) {
        CustomRunnable mr = new CustomRunnable();
        Thread t = new Thread(mr);
        System.out.println(t);
        t.run();
    }
}

class CustomRunnable implements Runnable {
    public void run() {
        // 覆盖该方法
        System.out.println("覆盖以前的方法");
    }
}

线程的启动

直接在上述代码中的 t.run() 后

直接追加 t.start()

 

在调用 start() 方法时,将创建一个新的控制线程,并加入线程队列,接着它将调用 run() 方法。 run() 方法中的代码定义执行线程所需的功能。

posted on 2017-03-14 00:33  weizhang715  阅读(81)  评论(0)    收藏  举报

导航