`
John_Kong19
  • 浏览: 272011 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Java语言基础:多线程

阅读更多
1.  有两种方法可以创建并运行一个线程:

•继承Thread类并覆盖Run方法,Run中的代码就在另一个线程执行。
view plaincopy to clipboardprint?
01.class MyThread extends Thread {  
02.    MyThread() {  
03.        // 调用下面代码,线程开始运行  
04.        start();  
05.    }  
06.   
07.    @Override 
08.    public void run() {  
09.        // 这里的代码是在线程中执行的  
10.        int i = 0;  
11.        while (i < 20)  
12.        {  
13.            System.out.println(i);  
14.            try {  
15.                sleep(100);  
16.            } catch (InterruptedException e) {  
17.                // TODO Auto-generated catch block  
18.                e.printStackTrace();  
19.            }  
20.            ++i;  
21.        }  
22.    }  
23.}  
24.   
25.public class Main {              
26.    public static void main(String[] args) {  
27.        MyThread myThread = new MyThread();  
28.    }  
29.} 
class MyThread extends Thread {
    MyThread() {
        // 调用下面代码,线程开始运行
        start();
    }

    @Override
    public void run() {
        // 这里的代码是在线程中执行的
        int i = 0;
        while (i < 20)
        {
            System.out.println(i);
            try {
                sleep(100);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            ++i;
        }
    }
}

public class Main {           
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
    }
}


•实现Runnable接口并传给新建的Thread类,实现类的Run方法即在另一个线程执行。
view plaincopy to clipboardprint?
01.// 实现Runnable接口  
02.public class Main implements Runnable {              
03.    @Override 
04.    public void run() {  
05.        // 这里的代码是在线程中执行的  
06.        int i = 0;  
07.        while (i < 20)  
08.        {  
09.            System.out.println(i);  
10.            try {  
11.                Thread.sleep(100);  
12.            } catch (InterruptedException e) {  
13.                // TODO Auto-generated catch block  
14.                e.printStackTrace();  
15.            }  
16.            ++i;  
17.        }  
18.    }  
19.   
20.    public static void main(String[] args) {  
21.        Main runable = new Main();  
22.        new Thread(runable).start();  
23.    }  
24.} 
// 实现Runnable接口
public class Main implements Runnable {           
    @Override
    public void run() {
        // 这里的代码是在线程中执行的
        int i = 0;
        while (i < 20)
        {
            System.out.println(i);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            ++i;
        }
    }

    public static void main(String[] args) {
        Main runable = new Main();
        new Thread(runable).start();
    }
}


2.  后台线程(daemon)不属于程序不可或缺的一部分,当程序存在非后台线程时,程序就不会终止;而如果非后台线程都结束了,此时不管有没有后台线程,程序都可以随时终止。要设定一个线程为后台线程,可以调用Thread.setDaemon(true),在一个后台线程中创建其他线程,这些线程也自动被设为后台线程:
view plaincopy to clipboardprint?
01.class MyThread extends Thread {  
02.    MyThread() {  
03.        // 把该线程设为后台线程  
04.        setDaemon(true);  
05.        // 调用下面代码,线程开始运行  
06.        start();  
07.    }  
08.   
09.    @Override 
10.    public void run() {  
11.        // 这里的代码是在线程中执行的  
12.        int i = 0;  
13.        while (i < 20)  
14.        {  
15.            System.out.println(i);  
16.            try {  
17.                sleep(100);  
18.            } catch (InterruptedException e) {  
19.                e.printStackTrace();  
20.            }  
21.            ++i;  
22.        }  
23.    }  
24.}  
25. 
26.public class Main{  
27.    public static void main(String[] args) {  
28.        MyThread mythread = new MyThread();  
29.        // mythread.run还没有执行完就结束程序了  
30.    }  
31.}  
32.// 程序只打印了0就结束了,而前面的例子程序会打印到19为止 
class MyThread extends Thread {
    MyThread() {
        // 把该线程设为后台线程
        setDaemon(true);
        // 调用下面代码,线程开始运行
        start();
    }

    @Override
    public void run() {
        // 这里的代码是在线程中执行的
        int i = 0;
        while (i < 20)
        {
            System.out.println(i);
            try {
                sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            ++i;
        }
    }
}

public class Main{
    public static void main(String[] args) {
        MyThread mythread = new MyThread();
        // mythread.run还没有执行完就结束程序了
    }
}
// 程序只打印了0就结束了,而前面的例子程序会打印到19为止

3.  在上面的例子中,如何让主线程等到后台线程结束时才结束呢?答案是调用后台线程的jion()方法,可以传入一个超时参数,如果不传则表示一直等到后台线程结束才返回:
view plaincopy to clipboardprint?
01.class MyThread extends Thread {  
02.    MyThread() {  
03.        // 把该线程设为后台线程  
04.        setDaemon(true);  
05.        // 调用下面代码,线程开始运行  
06.        start();  
07.    }  
08.   
09.    @Override 
10.    public void run() {  
11.        // 这里的代码是在线程中执行的  
12.        int i = 0;  
13.        while (i < 20)  
14.        {  
15.            System.out.println(i);  
16.            try {  
17.                sleep(100);  
18.            } catch (InterruptedException e) {  
19.                e.printStackTrace();  
20.            }  
21.            ++i;  
22.        }  
23.    }  
24.}  
25.   
26.public class Main{  
27.    public static void main(String[] args) {  
28.        MyThread mythread = new MyThread();  
29.        try {  
30.            // 等待后台线程结束  
31.            mythread.join();  
32.        } catch (InterruptedException e) {  
33.            e.printStackTrace();  
34.        }  
35.    }  
36.} 
class MyThread extends Thread {
    MyThread() {
        // 把该线程设为后台线程
        setDaemon(true);
        // 调用下面代码,线程开始运行
        start();
    }

    @Override
    public void run() {
        // 这里的代码是在线程中执行的
        int i = 0;
        while (i < 20)
        {
            System.out.println(i);
            try {
                sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            ++i;
        }
    }
}

public class Main{
    public static void main(String[] args) {
        MyThread mythread = new MyThread();
        try {
            // 等待后台线程结束
            mythread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
4. 当两个线程同时读写同一份数据时,可能会引起资源冲突,这时就需要在并行机制之外,再提供一种同步机制,使对数据的读写可以有序的进行,Java对此的处理非常简单,就是使用synchronized关键字:
•在普通方法前面加上synchronized,使得这个方法变成同步方法,先看下面例子,当主线程和工作线程同时调用synProc时,谁先调用到,谁就获得一个锁,另外一个只能等待,这样就保持在多线程环境下调用这个方法是有序的:
view plaincopy to clipboardprint?
01.class MyThread extends Thread {  
02.    MyThread() {  
03.        start();  
04.    }  
05.   
06.    @Override 
07.    public void run() {  
08.        synProc();  
09.    }  
10.   
11.    synchronized public void synProc(){  
12.        int count = 0;  
13.        while (count++ < 10) {  
14.            try {  
15.                sleep(100);  
16.                System.out.println("synProc: " + count);  
17.            } catch (InterruptedException e) {  
18.                e.printStackTrace();  
19.            }  
20.        }  
21.    }  
22.}  
23.   
24.public class Main{  
25.    public static void main(String[] args) {  
26.        MyThread thread = new MyThread();  
27.        thread.synProc();  
28.    }  
29.}  
30.// 输出结果是:  
31.synProc: 1 
32.synProc: 2 
33.synProc: 3 
34.synProc: 4 
35.synProc: 5 
36.synProc: 6 
37.synProc: 7 
38.synProc: 8 
39.synProc: 9 
40.synProc: 10 
41.synProc: 1 
42.synProc: 2 
43.synProc: 3 
44.synProc: 4 
45.synProc: 5 
46.synProc: 6 
47.synProc: 7 
48.synProc: 8 
49.synProc: 9 
50.synProc: 10 
class MyThread extends Thread {
    MyThread() {
        start();
    }

    @Override
    public void run() {
        synProc();
    }

    synchronized public void synProc(){
        int count = 0;
        while (count++ < 10) {
            try {
                sleep(100);
                System.out.println("synProc: " + count);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class Main{
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.synProc();
    }
}
// 输出结果是:
synProc: 1
synProc: 2
synProc: 3
synProc: 4
synProc: 5
synProc: 6
synProc: 7
synProc: 8
synProc: 9
synProc: 10
synProc: 1
synProc: 2
synProc: 3
synProc: 4
synProc: 5
synProc: 6
synProc: 7
synProc: 8
synProc: 9
synProc: 10


•其实synchronized方法是在对象级别上的,每个对象都有一个锁,当调用它的任意一个同步方法时,就是去获得这个对象锁,当获得对象锁时,其他同步方法也不能同时被调用了,只能等这个方法执行完才可以被调用,下面代码清楚地说明这一点:
view plaincopy to clipboardprint?
01.class MyThread extends Thread {  
02.    MyThread() {  
03.        start();  
04.    }  
05.   
06.    @Override 
07.    public void run() {  
08.        synProc();  
09.    }  
10.   
11.    synchronized public void synProc(){  
12.        int count = 0;  
13.        while (count++ < 10) {  
14.            try {  
15.                sleep(100);  
16.                System.out.println("synProc: " + count);  
17.            } catch (InterruptedException e) {  
18.                e.printStackTrace();  
19.            }  
20.        }  
21.    }  
22.   
23.    synchronized public void synProc2() {  
24.        int count = 0;  
25.        while (count++ < 10) {  
26.            try {  
27.                sleep(100);  
28.                System.out.println("synProc2: " + count);  
29.            } catch (InterruptedException e) {  
30.                e.printStackTrace();  
31.            }  
32.        }  
33.    }  
34.}  
35.   
36.public class Main{  
37.    public static void main(String[] args) {  
38.        MyThread thread = new MyThread();  
39.        thread.synProc2();  
40.    }  
41.}  
42.// 输出  
43.synProc2: 1 
44.synProc2: 2 
45.synProc2: 3 
46.synProc2: 4 
47.synProc2: 5 
48.synProc2: 6 
49.synProc2: 7 
50.synProc2: 8 
51.synProc2: 9 
52.synProc2: 10 
53.synProc: 1 
54.synProc: 2 
55.synProc: 3 
56.synProc: 4 
57.synProc: 5 
58.synProc: 6 
59.synProc: 7 
60.synProc: 8 
61.synProc: 9 
62.synProc: 10 
class MyThread extends Thread {
    MyThread() {
        start();
    }

    @Override
    public void run() {
        synProc();
    }

    synchronized public void synProc(){
        int count = 0;
        while (count++ < 10) {
            try {
                sleep(100);
                System.out.println("synProc: " + count);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    synchronized public void synProc2() {
        int count = 0;
        while (count++ < 10) {
            try {
                sleep(100);
                System.out.println("synProc2: " + count);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class Main{
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.synProc2();
    }
}
// 输出
synProc2: 1
synProc2: 2
synProc2: 3
synProc2: 4
synProc2: 5
synProc2: 6
synProc2: 7
synProc2: 8
synProc2: 9
synProc2: 10
synProc: 1
synProc: 2
synProc: 3
synProc: 4
synProc: 5
synProc: 6
synProc: 7
synProc: 8
synProc: 9
synProc: 10

•synchronized可以加到静态方法前面,每个类也有一个锁,调用同步静态方法就是获得类级别的锁,这使类中的所有同步静态方法变得有序,即只有一个同步静态方法被调用,其他的同步静态就只好等待它结束才能被调用。
•synchronized还可以加在方法之内,称为同步块,如synchronized(obj){...}这样的语法,这里其实是获得obj对象的锁,因此Obj的同步方法也会受它影响,即对于Obj的同步块被执行时,Obj的同步方法必须等同步块执行完才能被调用:
view plaincopy to clipboardprint?
01.class MyThread extends Thread {  
02.    MyThread() {  
03.        start();  
04.    }  
05.   
06.    @Override 
07.    public void run() {  
08.        synProc();  
09.    }  
10.   
11.    public void synProc(){  
12.        int count = 0;          
13.        synchronized (this) {  
14.            do {  
15.                try {  
16.                    sleep(50);  
17.                } catch (InterruptedException e) {  
18.                    e.printStackTrace();  
19.                }  
20.                System.out.println("synProc :" + count);  
21.            } while (count++ < 3);          
22.        }  
23.    }  
24.   
25.    synchronized public void synProc2() {  
26.        int count = 0;  
27.        do {  
28.            try {  
29.                sleep(50);  
30.            } catch (InterruptedException e) {  
31.                e.printStackTrace();  
32.            }  
33.            System.out.println("synProc2 :" + count);  
34.        } while (count++ < 3);  
35.    }  
36.}  
37.   
38.public class Main{  
39.    public static void main(String[] args) {  
40.        MyThread thread = new MyThread();  
41.        thread.synProc2();  
42.    }  
43.}  
44.// 输出:  
45.synProc2 :0 
46.synProc2 :1 
47.synProc2 :2 
48.synProc2 :3 
49.synProc :0 
50.synProc :1 
51.synProc :2 
52.synProc :3 
class MyThread extends Thread {
    MyThread() {
        start();
    }

    @Override
    public void run() {
        synProc();
    }

    public void synProc(){
        int count = 0;       
        synchronized (this) {
            do {
                try {
                    sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("synProc :" + count);
            } while (count++ < 3);       
        }
    }

    synchronized public void synProc2() {
        int count = 0;
        do {
            try {
                sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("synProc2 :" + count);
        } while (count++ < 3);
    }
}

public class Main{
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.synProc2();
    }
}
// 输出:
synProc2 :0
synProc2 :1
synProc2 :2
synProc2 :3
synProc :0
synProc :1
synProc :2
synProc :3

5.  线程之间的等待与通知通过wait和notify,notifyAll来实现。

•这三个方法都必须在对象的同步块中执行,否则运行期会出现IllegalMonitorStateException异常。
•当线程A调用Obj.wait()时,A将被挂起,直到另一个线程B调用Obj.notify()或Obj.notifyAll(),A才被重新唤醒。
•如果只有一个线程调用Obj.wait(),另一个线程只需要调用Obj.notify()即可;但如果有多个线程调用Obj.wait(),则另一个线程必须调用Obj.notifyAll()才可以将所有的线程唤醒。
下面代码演示了一个writer和多个reader的协作过程:

view plaincopy to clipboardprint?
01.class Writer extends Thread {      
02.    private char chr;  
03.   
04.    @Override 
05.    public void run() {          
06.        for (char c = 'A'; c <= 'Z'; ++c){  
07.            chr = c;  
08.            // 通知Reader可以读了  
09.            synchronized (this) {  
10.                notifyAll();  
11.            }  
12.            // 过会儿再写  
13.            try {  
14.                sleep(100);  
15.            } catch (InterruptedException e) {  
16.                e.printStackTrace();  
17.            }  
18.        }  
19.    }  
20.   
21.    public char getChar() {  
22.        return chr;  
23.    }  
24.}  
25.   
26.class Reader extends Thread {  
27.    private Writer writer;  
28.   
29.    Reader(Writer writer) {  
30.        this.writer = writer;  
31.        start();  
32.    }  
33.   
34.    @Override 
35.    public void run() {  
36.        while (true){  
37.            // 等待Writer写  
38.            synchronized (writer) {  
39.                try {  
40.                    // 此处Reader线程将被挂起  
41.                    writer.wait();  
42.                } catch (InterruptedException e) {  
43.                    e.printStackTrace();  
44.                }  
45.            }  
46.            // 读取Writer写的内容  
47.            char chr = writer.getChar();  
48.            System.out.print(chr + " ");  
49.            // 读到Z即结束  
50.            if (chr == 'Z') {  
51.                System.out.println();  
52.                break;  
53.            }  
54.        }  
55.    }  
56.}  
57.   
58.public class Main{  
59.    public static void main(String[] args) {  
60.        Writer writer = new Writer();  
61.        Reader reader1 = new Reader(writer);  
62.        Reader reader2 = new Reader(writer);  
63.        // 开始  
64.        writer.start();  
65.    }  
66.}  
67.// 最后的输出是:  
68.A A B B C C D D E E F F G G H H I I J J K K L L M M N N O O P P Q Q R R S S T T U U V V W W X X Y Y Z   
69.Z 



本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/linzhengqun/archive/2011/04/02/6296458.aspx
分享到:
评论

相关推荐

    java并发编程:线程基础

    本资源致力于向您介绍 Java 并发编程中的线程基础,涵盖了多线程编程的核心概念、线程的创建和管理,以及线程间通信的基本方法。通过深入学习,您将建立扎实的多线程编程基础,能够更好地理解和应用多线程编程。 多...

    java应用与开发 Java实验,综合应用 运用Java语言的各方面知识解决实际问题,提高综合编程能力

    用途: 学习Java语言的控制语法,掌握基础语法知识。 实验二: 关键词: Java的类 内容关键词: 类,Java实验 用途: 学习Java中的类的概念和使用,深入理解面向对象编程。 实验三: 关键词: 异常处理机制与数据流 内容...

    Java程序设计基础:Java语言概述.pptx

    Java开发基础--Java语言概述 Java语言概述 了解Java语言历史和特点 理解Java语言规范 能够区分API、JDK的含义 Java的发展历史 1991年,Sun公司James Gosling领导的Green小组创建了一种新型语言,命名为Oak(橡树),...

    Java实验指导书_多线程

    Java实验指导书_多线程 《Java语言程序设计基础教程》 上机实验指导手册 异常处理 【目的】 ①线程的创建和运行 ②Thread类的sleep、join等方法的使用 ③线程同步

    完整版 Java编程基础入门教程 Java语言程序设计 第8章_多线程与异常处理(共72页).ppt

    【完整课程列表】 完整版 Java编程基础入门教程 ...完整版 Java编程基础入门教程 Java语言程序设计 第8章_多线程与异常处理(共72页).ppt 完整版 Java编程基础入门教程 Java语言程序设计 第9章_Applet(共40页).ppt

    完整版 Java高级教程 Java语言程序设计 第2章 Java多线程(共24页).ppt

    完整版 Java高级教程 Java语言程序设计 第2章 Java多线程(共24页).ppt 完整版 Java高级教程 Java语言程序设计 第2章 哲学家的故事(共7页).ppt 完整版 Java高级教程 Java语言程序设计 第3章 Java网络基础知识(共...

    Java实验6多线程.doc

    本专栏主要为Java程序设计(基础)实验报告和Java程序设计(进阶)实验报告,基础篇有JAVA环境搭建、Java语言基础、方法和数组、面向对象基础、Java常用类、继承与接口、成员访问控制与异常、JavaFX程序设计、Java...

    完整版java基础入门教程由浅入深讲解 Java语言编程基础 含辅助PPT资料 全套PPT课件 共15个章节.rar

    完整版java基础入门教程由浅入深讲解 Java语言编程基础 第13章 多线程(共50页).ppt 完整版java基础入门教程由浅入深讲解 Java语言编程基础 第14章 网络通信(共76页).ppt 完整版java基础入门教程由浅入深讲解 ...

    Java高并发编程详解:多线程与架构设计 (Java核心技术系列)

    部分主要阐述Thread的基础知识,详细介绍线程的API使用、线程安全、线程间数据通信,以及如何保护共享资源等内容,它是深入学习多线程内容的基础。 第二部分引入了ClassLoader,这是因为ClassLoader与线程不无关系,...

    Java语言基础 Java网络编程技术 Java程序设计使用教程 第10章 网络通信(共53页).ppt

    Java语言基础 Java网络编程技术 Java程序设计使用教程 第07章 多线程(共44页).ppt Java语言基础 Java网络编程技术 Java程序设计使用教程 第08章 Applet应用程序(共34页).ppt Java语言基础 Java网络编程技术 Java...

    Java语言程序设计(基础篇)文字版

    本书是Java语言的经典教材,中文版分为《Java语言程序设计基础篇》和《Java语 言程序设计进阶篇》。基础篇从Java语言的特点入手,介绍了语法结构、面向对象程序 设计基础知识到面向对象程序设计、图形用户界面设计、...

    完整版 Java编程基础入门教程 Java语言程序设计 第2章_语言基础(共45页).ppt

    【完整课程列表】 完整版 Java编程基础入门教程 ...完整版 Java编程基础入门教程 Java语言程序设计 第8章_多线程与异常处理(共72页).ppt 完整版 Java编程基础入门教程 Java语言程序设计 第9章_Applet(共40页).ppt

    完整版 Java编程基础入门教程 Java语言程序设计 第1章_java概述(共50页).ppt

    【完整课程列表】 完整版 Java编程基础入门教程 ...完整版 Java编程基础入门教程 Java语言程序设计 第8章_多线程与异常处理(共72页).ppt 完整版 Java编程基础入门教程 Java语言程序设计 第9章_Applet(共40页).ppt

    完整版精品java课件 Java基础入门教程 Java程序设计 第13章 多线程(共24页).ppt

    完整版精品java课件 Java基础入门教程 Java程序设计 第2章 java语言基础(共31页).ppt 完整版精品java课件 Java基础入门教程 Java程序设计 第3章 控制结构(共23页).ppt 完整版精品java课件 Java基础入门教程 Java...

    解析Java的多线程机制

    Unix操作系统环境下,应用程序可以利用fork... 可以说:Java语言对应用程序多线程能力的支持增强了Java作为网络程序设计语言的优势,为实现分布式应用系统中多客户端的并发访问以及提高服务器的响应效率奠定坚实基础。

    Java多线程编程的优点和缺点

    支持并发编程:多线程编程是支持并发编程的基础,可以处理多个并发任务,如服务器处理多个客户端请求。 缺点: 竞态条件(Race Conditions):多个线程访问共享资源时可能引发竞态条件,导致数据不一致性和程序错误...

    Java学习用例demo

    Java的基础知识点包括Java语言基础、面向对象、Java8新特性以及Java应用,其中Java语言基础包括环境搭建、基本数据类型、变量、常量定义、控制结构等,它们为学习编程语言打下了很好的基础;面向对象是任何编程语言...

    java多线程编程实战指南 核心篇 代码

    随着现代处理器的生产工艺从提升...《Java多线程编程实战指南(核心篇)》适合有一定Java语言基础的读者作为入门多线程编程之用,也适合有一定多线程编程经验的读者作为重新梳理知识结构以提升认知层次和参考之用。

    Java高手真经 编程基础卷.part1.rar

    《Java高手真经(编程基础卷):Java核心编程技术》详细讲解了Java语言基础开发中的各种技术,主要内容包括如下。Java开发入门:JDK、JVM、Eclipse、Linux。Java语法基础:类、抽象类、接口、内部类、匿名类、异常、...

    Java高手真经 编程基础卷.part3.rar

    《Java高手真经(编程基础卷):Java核心编程技术》详细讲解了Java语言基础开发中的各种技术,主要内容包括如下。Java开发入门:JDK、JVM、Eclipse、Linux。Java语法基础:类、抽象类、接口、内部类、匿名类、异常、...

Global site tag (gtag.js) - Google Analytics