做事做精

Java多线程理解

一、理论概念

进程与线程

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位。

线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.

进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

 

二、线程的Java实现

目前实现java线程有2种方式,继承Thread类和实现Runnable接口,重写run方法。

1、实现Runnable接口

实现 Runnable的接口的好处是实现变量的共享,多个线程使用同一个Runable对象,如上代码块中的成员变量j:

package src;

/**
 * 
 * @author Shawn Wang
 * 
 */
public class MyThread implements Runnable {
    private int j = 100;

    @Override
    public void run() {
        while (true) {
            if (j > 0) {
                System.out.println(Thread.currentThread().getName() + "-- num:"
                        + j--);
            } else {
                break;
            }
        }
    }

    public static void main(String[] args) {
        MyThread mt = new MyThread();
        Thread thread1 = new Thread(mt);
        Thread thread2 = new Thread(mt);
        Thread thread3 = new Thread(mt);
        thread1.start();
        thread2.start();
        thread3.start();
    }
}
View Code

输出结果:

Thread-1-- num:100
Thread-3-- num:98
Thread-2-- num:99
Thread-2-- num:95
Thread-3-- num:96
Thread-1-- num:97
Thread-1-- num:92
Thread-1-- num:91
Thread-3-- num:93
Thread-3-- num:89
Thread-3-- num:88
Thread-2-- num:94
Thread-2-- num:86
Thread-2-- num:85
Thread-2-- num:84
Thread-3-- num:87
Thread-3-- num:82
Thread-1-- num:90
Thread-1-- num:80
Thread-3-- num:81
Thread-3-- num:78
Thread-3-- num:77
Thread-3-- num:76
Thread-3-- num:75
Thread-3-- num:74
Thread-2-- num:83
Thread-2-- num:72
Thread-2-- num:71
Thread-2-- num:70
Thread-3-- num:73
Thread-1-- num:79
Thread-3-- num:68
Thread-3-- num:66
Thread-3-- num:65
Thread-2-- num:69
Thread-2-- num:63
Thread-2-- num:62
Thread-2-- num:61
Thread-2-- num:60
Thread-2-- num:59
Thread-2-- num:58
Thread-2-- num:57
Thread-2-- num:56
Thread-2-- num:55
Thread-2-- num:54
Thread-2-- num:53
Thread-2-- num:52
Thread-3-- num:64
Thread-1-- num:67
Thread-3-- num:50
Thread-2-- num:51
Thread-3-- num:48
Thread-1-- num:49
Thread-3-- num:46
Thread-2-- num:47
Thread-3-- num:44
Thread-1-- num:45
Thread-3-- num:42
Thread-2-- num:43
Thread-3-- num:40
Thread-1-- num:41
Thread-3-- num:38
Thread-2-- num:39
Thread-3-- num:36
Thread-1-- num:37
Thread-3-- num:34
Thread-2-- num:35
Thread-3-- num:32
Thread-1-- num:33
Thread-3-- num:30
Thread-2-- num:31
Thread-3-- num:28
Thread-1-- num:29
Thread-3-- num:26
Thread-2-- num:27
Thread-3-- num:24
Thread-1-- num:25
Thread-3-- num:22
Thread-2-- num:23
Thread-3-- num:20
Thread-1-- num:21
Thread-3-- num:18
Thread-2-- num:19
Thread-3-- num:16
Thread-1-- num:17
Thread-3-- num:14
Thread-2-- num:15
Thread-3-- num:12
Thread-1-- num:13
Thread-3-- num:10
Thread-2-- num:11
Thread-3-- num:8
Thread-1-- num:9
Thread-3-- num:6
Thread-2-- num:7
Thread-3-- num:4
Thread-1-- num:5
Thread-3-- num:2
Thread-2-- num:3
Thread-1-- num:1
result

2、继承Thread类

package src;

public class ThreadClient extends Thread {

    public ThreadClient(String name) {
        super(name);
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        for (int i = 0; i <= 10; i++) {
            System.out.println(currentThread().getName() + ":" + i);
        }
    }
   
    public static void main(String[] args) {
        ThreadClient thread1 = new ThreadClient("thread1");
        ThreadClient thread2 = new ThreadClient("thread1");
        ThreadClient thread3 = new ThreadClient("thread1");
        thread1.start();
        thread2.start();
        thread3.start();
    }

}
View Code

输出结果

thread1:0
thread1:1
thread1:0
thread1:1
thread1:0
thread1:1
thread1:2
thread1:3
thread1:4
thread1:5
thread1:6
thread1:2
thread1:2
thread1:3
thread1:4
thread1:3
thread1:4
thread1:5
thread1:6
thread1:7
thread1:7
thread1:8
thread1:9
thread1:10
thread1:5
thread1:6
thread1:7
thread1:8
thread1:9
thread1:8
thread1:9
thread1:10
thread1:10
result

疑问:

为什么要重写 run方法?

run方法时存储线程所要运行的代码,不能在直接调用run方法,需要通过start方法来调用。

三、线程同步

场景:如果线程进行了sleep 操作时,其他线程对共享变量做了改变,会造成数据不同步问题。

package src;

/**
 * 
 * @author Shawn Wang
 * 
 */
public class MyThread implements Runnable {
    private int j = 100;

    @Override
    public void run() {
        while (true) {
            if (j > 0) {
                try {
                    Thread.sleep(1000);// 当前线程休眠1秒
                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "-- num:"
                        + j--);
            } else {
                break;
            }
        }
    }

    public static void main(String[] args) {
        MyThread mt = new MyThread();
        Thread thread1 = new Thread(mt);
        Thread thread2 = new Thread(mt);
        Thread thread3 = new Thread(mt);
        thread1.start();
        thread2.start();
        thread3.start();
    }
}
View Code

输出结果:

Thread-1-- num:100
Thread-2-- num:99
Thread-3-- num:98
Thread-1-- num:97
Thread-3-- num:95
Thread-2-- num:96
Thread-1-- num:94
Thread-2-- num:92
Thread-3-- num:93
Thread-3-- num:91
Thread-2-- num:90
Thread-1-- num:90
Thread-3-- num:89
Thread-2-- num:88
Thread-1-- num:87
Thread-3-- num:86
Thread-2-- num:85
Thread-1-- num:85
Thread-3-- num:84
Thread-2-- num:83
Thread-1-- num:82
Thread-3-- num:81
Thread-1-- num:80
Thread-2-- num:80
Thread-3-- num:79
Thread-2-- num:77
Thread-1-- num:78
Thread-3-- num:76
Thread-2-- num:75
Thread-1-- num:74
Thread-2-- num:73
Thread-3-- num:71
Thread-1-- num:72
Thread-2-- num:70
Thread-1-- num:69
Thread-3-- num:69
Thread-2-- num:68
Thread-3-- num:66
Thread-1-- num:67
Thread-2-- num:65
Thread-1-- num:64
Thread-3-- num:64
Thread-2-- num:63
Thread-1-- num:62
Thread-3-- num:61
Thread-2-- num:60
Thread-3-- num:58
Thread-1-- num:59
Thread-2-- num:57
Thread-1-- num:56
Thread-3-- num:56
Thread-2-- num:55
Thread-1-- num:54
Thread-3-- num:54
Thread-2-- num:53
Thread-3-- num:52
Thread-1-- num:52
Thread-3-- num:51
Thread-2-- num:50
Thread-1-- num:51
Thread-3-- num:49
Thread-1-- num:48
Thread-2-- num:48
Thread-3-- num:47
Thread-1-- num:46
Thread-2-- num:45
Thread-1-- num:44
Thread-2-- num:42
Thread-3-- num:43
Thread-3-- num:40
Thread-1-- num:39
Thread-2-- num:41
Thread-2-- num:38
Thread-3-- num:37
Thread-1-- num:38
Thread-1-- num:36
Thread-2-- num:35
Thread-3-- num:36
Thread-1-- num:34
Thread-2-- num:33
Thread-3-- num:33
Thread-1-- num:32
Thread-3-- num:30
Thread-2-- num:31
Thread-1-- num:29
Thread-3-- num:29
Thread-2-- num:29
Thread-3-- num:28
Thread-1-- num:28
Thread-2-- num:28
Thread-1-- num:27
Thread-2-- num:26
Thread-3-- num:27
Thread-1-- num:25
Thread-2-- num:24
Thread-3-- num:24
Thread-1-- num:23
Thread-3-- num:22
Thread-2-- num:22
Thread-1-- num:21
Thread-3-- num:20
Thread-2-- num:20
Thread-1-- num:19
Thread-3-- num:18
Thread-2-- num:17
Thread-3-- num:16
Thread-1-- num:15
Thread-2-- num:14
Thread-2-- num:13
Thread-3-- num:12
Thread-1-- num:13
Thread-2-- num:11
Thread-1-- num:10
Thread-3-- num:10
Thread-2-- num:9
Thread-1-- num:7
Thread-3-- num:8
Thread-2-- num:6
Thread-3-- num:5
Thread-1-- num:5
Thread-2-- num:4
Thread-3-- num:3
Thread-1-- num:2
Thread-2-- num:1
Thread-1-- num:0
Thread-3-- num:-1
result

出现了负数。

解决加上同步锁synchronized

同步代码块的格式:
    synchronized(对象){
           需要被同步的代码;
    } 

package src;

/**
 * 
 * @author Shawn Wang
 * 
 */
public class MyThread implements Runnable {
    private int j = 100;

    @Override
    public void run() {
        while (true) {
            synchronized (this) {
                if (j > 0) {
                    try {
                        Thread.sleep(1000);// 当前线程休眠1秒
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()
                            + "-- num:" + j--);
                } else {
                    break;
                }
            }
        }
    }

    public static void main(String[] args) {
        MyThread mt = new MyThread();
        Thread thread1 = new Thread(mt);
        Thread thread2 = new Thread(mt);
        Thread thread3 = new Thread(mt);
        thread1.start();
        thread2.start();
        thread3.start();
    }
}
View Code

 

posted @ 2015-09-17 17:56  王啸shawn  阅读(300)  评论(1编辑  收藏  举报