`

多线程 基础

阅读更多

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

  • 继承Thread类并覆盖Run方法,Run中的代码就在另一个线程执行。

         

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方法即在另一个线程执行。 
  •    // 实现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),在一个后台线程中创建其他线程,这些线程也自动被设为后台线程:


    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()方法,可以传入一个超时参数,如果不传则表示一直等到后台线程结束才返回:

    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时,谁先调用到,谁就获得一个锁,另外一个只能等待,这样就保持在多线程环境下调用这个方法是有序的:
          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方法是在对象级别上的,每个对象都有一个锁,当调用它的任意一个同步方法时,就是去获得这个对象锁,当获得对象锁时,其他同步方法也不能同时被调用了,只能等这个方法执行完才可以被调用,下面代码清楚地说明这一点:

    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的同步方法必须等同步块执行完才能被调用:  
          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的协作过程:
         class Writer extends Thread {
        private char chr;
     
        @Override
        public void run() {        
            for (char c = 'A'; c <= 'Z'; ++c){
                chr = c;
                // 通知Reader可以读了
                synchronized (this) {
                    notifyAll();
                }
                // 过会儿再写
                try {
                    sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
     
        public char getChar() {
            return chr;
        }
    }
     
    class Reader extends Thread {
        private Writer writer;
     
        Reader(Writer writer) {
            this.writer = writer;
            start();
        }
     
        @Override
        public void run() {
            while (true){
                // 等待Writer写
                synchronized (writer) {
                    try {
                        // 此处Reader线程将被挂起
                        writer.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                // 读取Writer写的内容
                char chr = writer.getChar();
                System.out.print(chr + " ");
                // 读到Z即结束
                if (chr == 'Z') {
                    System.out.println();
                    break;
                }
            }
        }
    }
     
    public class Main{
        public static void main(String[] args) {
            Writer writer = new Writer();
            Reader reader1 = new Reader(writer);
            Reader reader2 = new Reader(writer);
            // 开始
            writer.start();
        }
    }
    // 最后的输出是:
    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 
    Z

     








     

    分享到:
    评论

    相关推荐

      C#多线程基础

      ### C#多线程基础详解 #### 知识点一:多线程概念与优势 在C#中,多线程是指一个程序中同时执行多个线程的能力。一个线程是程序执行的基本单位,每个线程都有自己的指令指针、栈和局部变量,但共享相同的内存空间...

      多线程基础与基于多线程的简单聊天室

      本压缩包“多线程基础与基于多线程的简单聊天室”提供了对多线程技术的实践理解和二次开发的基础。以下是关于这个主题的详细知识点: 1. **多线程的概念**:多线程是指在一个程序中同时执行多个不同的线程,每个...

      多线程基础个人总结思维导图

      在IT行业中,多线程是程序并发执行的一种方式,它极大地提高了系统资源的利用率和程序...在学习过程中,可以参考"多线程基础总结01.bmp"和"多线程基础总结01.mmap"等文件,它们可能提供了更为详细和直观的结构化知识。

      CSharp多线程基础教程

      本教程将深入探讨C#中的多线程基础,包括创建线程、线程同步与通信、线程池以及线程安全等内容。 一、线程创建 在C#中,有两种主要方式来创建线程:使用`System.Threading.Thread`类和使用`System.Threading.Tasks...

      JAVA多线程基础演练DEMO

      这个"JAVA多线程基础演练DEMO"提供了一些基础示例,帮助开发者更好地理解和掌握多线程的基本概念和用法。以下将详细讲解Java多线程的相关知识点: 1. **线程的创建** - **继承Thread类**:创建一个新类,继承自`...

      多线程基础知识

      通过学习和掌握这些多线程基础知识,开发者能够编写出更加高效、稳定的并发程序,提升软件系统的性能和用户体验。同时,对多线程深入理解也有助于应对面试中的技术考察,为职业生涯的晋升铺平道路。

      java多线程基础资料

      Java多线程是Java编程中的一个...以上只是Java多线程基础知识的一部分,深入学习还包括线程池的配置与优化、线程安全的设计模式、并发工具类的使用等。理解和掌握这些知识点对于编写高效、稳定的多线程程序至关重要。

      C#多线程基础教程

      C#多线程是编程中的重要概念,尤其在开发高性能...总的来说,理解和掌握C#多线程基础知识对于编写高效、健壮的程序至关重要。在实际开发中,应合理利用多线程,注意线程安全,避免潜在的问题,提升软件的稳定性和性能。

      MFC多线程基础解析及例子

      **多线程基础** 多线程是指在一个进程中可以同时运行多个独立的执行流,每个执行流被称为一个线程。在MFC中,我们可以使用`CWinThread`类来创建和管理线程。`CWinThread`是MFC对Windows API中的`_beginthreadex`和`...

      java多线程基础篇讲解

      Java多线程基础篇讲解是针对初学者设计的教程,旨在用简洁明了的语言帮助学习者更容易理解多线程的概念和应用。多线程编程在现代计算机系统中扮演着重要角色,尤其在CPU主频发展遇到瓶颈的情况下,通过超线程技术和...

      多线程基础代码.rar

      "多线程基础代码.rar"这个压缩包文件很可能是包含了一些关于多线程编程的基础示例代码,用于帮助初学者理解和实践多线程技术。 多线程允许一个应用程序同时执行多个不同的任务,每个任务被称为一个线程。在Java、C#...

      多线程基础部分.md,学习代码

      我们将围绕标题“多线程基础部分”展开,结合描述和标签,重点关注Java中的多线程、软件设计以及并发编程的相关概念。 首先,让我们理解什么是多线程。在计算机科学中,线程是程序执行的基本单位,一个进程可以包含...

      java多线程基础知识

      Java多线程基础知识 Java多线程基础知识是Java编程语言中的一项重要技术,用于提高程序的执行效率和响应速度。在这里,我们将详细介绍Java多线程基础知识的相关概念和技术。 一、程序、进程和线程 程序(Program...

      多线程基础总结.xmind

      多线程基础理论, 多线程中常用API,多线程的实现方式, 线程池以及创建线程池相关API, 常见的设计模式等内容

      C#多线程基础教程--

      本教程将深入探讨C#中的多线程基础知识,以及如何通过实例来实现线程的控制和通信。 首先,我们需要理解线程的基本概念。在操作系统中,线程是执行单元,它代表程序的一个执行流程。每个线程拥有自己的栈空间,用于...

      VC++多线程基础编程源程序

      对于初学者来说,理解并掌握多线程基础编程至关重要,因为这能帮助他们构建更加高效和复杂的软件系统。在这个"VC++多线程基础编程源程序"中,我们将探讨如何利用Visual Studio 2008来实现多线程功能,特别是通过创建...

      Java多线程干货系列(1)Java多线程基础编程开发技术

      Java多线程是Java编程中的重要...以上内容仅涵盖了Java多线程基础编程的一部分知识点,实际开发中还需要关注更多的并发控制策略、性能优化和调试技巧。对于深入理解Java多线程,还需要学习和实践更多相关的高级特性。

      C# 多线程基础练习

      C# 多线程基础练习,需要学习多线程的小伙伴们快来下载吧

      JAVA多线程基础

      ### JAVA多线程基础知识详解 #### 一、Java多线程概述 在计算机科学中,**多线程**是一种能够使程序内部同时执行多个任务的技术。这种技术在现代软件开发中至关重要,尤其是在需要处理大量计算任务或者需要进行...

    Global site tag (gtag.js) - Google Analytics