理解 Java 多线程

并发与并行

并发:指两个或多个事件在同一时间段内发生。

并行:指两个或多个事件在同一时刻发生(同时发生)。

进程与线程

进程:

是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡的过程。

线程:

线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。

简而言之:

一个程序运行后至少有一个进程,一个进程中可以包含多个线程。

线程调度

分时调度:

所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间。

抢占式调度:

优先让优先级高的銭程使用CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度。

Java中的主线程

主线程:执行主(main)方法的线程。

 

单线程

单线程:Java程序中,只有一个线程,执行从main方法开始,从上到下的执行。

举例

public class Student {

    public static void method1() {
        for (int i = 0; i < 5; i++) {
            System.out.println("我正在执行Student的方法1");
        }
    }

    public static void method2() {
        for (int i = 0; i < 5; i++) {
            System.out.println("我正在执行Student的方法2");
        }
    }

    public Student() {
    }

}
public class Demo01MainThread {
    public static void main(String[] args) {
        Student.method1();
        Student.method2();
    }
}
控制台输出:
我正在执行Student的方法1
我正在执行Student的方法1
我正在执行Student的方法1
我正在执行Student的方法1
我正在执行Student的方法1
我正在执行Student的方法2
我正在执行Student的方法2
我正在执行Student的方法2
我正在执行Student的方法2
我正在执行Student的方法2

从控制台输出可以知道,程序从上到下的执行,从方法1开始执行,到方法2开始执行。

多线程

创建多线程程序的第一种方式

创建Thread类的子类
java.lang.Thread类:是描述线程的类,我们想要实现多线程程序,就必须继承Thread类
实现步骤:

  1. 创建一个 Thread类的子类。
  2. 在Thread类的子类中重写Thread类中的run方法,设置线程任务(开启线程要做什么)。
  3. 创建Thread类的子类对象。
  4. 调用Thread类中的start方法,开启新的线程,执行run方法

void start()使该线程开始执行。Java虚拟机调用该线程的run方法。结果是两个线程并发地运行;当前线程(main线程)和另一个线程(创建的新线程,执行其run方法)。多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。Java程序属于抢占式调度,哪个线程的优先级高,哪个线程优先执行;同一个优先级,随机选择一个执行。

例子:

public class Person extends Thread {

    /**
     * 重写Thread类的run方法,设置任务
     */
    @Override
    public void run() {
        for (int i = 0; i < 6; i++) {
            System.out.println("我正在执行重写的run方法中的线程:" + i);
        }
    }

}
public class Demo02MainThread {
    public static void main(String[] args) {
        // 创建Thread的子类对象
        Thread myThread = new Person();
        // 调用Thread类中的start方法,开启新的线程,执行run方法
        myThread.start();

        // main方法中的要执行的线程
        for (int i = 0; i < 6; i++) {
            System.out.println("我正在执行main方法的线程:" + i);
        }

    }
}
控制台输出:
我正在执行main方法的线程:0
我正在执行main方法的线程:1
我正在执行重写的run方法中的线程:0
我正在执行main方法的线程:2
我正在执行重写的run方法中的线程:1
我正在执行重写的run方法中的线程:2
我正在执行重写的run方法中的线程:3
我正在执行重写的run方法中的线程:4
我正在执行重写的run方法中的线程:5
我正在执行main方法的线程:3
我正在执行main方法的线程:4
我正在执行main方法的线程:5

多线程的原理

Thread类的常用方法

public String getName():获取当前线程名称。
public void start():导致此线程开始执行;Java虚拟机调用此线程的run方法。
public void run():此线程要执行的任务在此处定义代码。
public static void sleep(long millis):使当前正在执行的线程以指定的亳秒数暂停(暂时停止执行)。
public static Thread currentThread()返回对当前正在执行的线程对象的引用。

getName()方法、start()方法、run()方法

public class MyThread extends Thread {
    @Override
    public void run() {
        // 此线程要执行的任务
    }
}
public class Demo01MyThread {

    public static void main(String[] args) {

        MyThread myThread1 = new MyThread();
        myThread1.start();
        String run1Name = myThread1.getName();

        MyThread myThread2 = new MyThread();
        myThread2.start();
        String run2Name = myThread2.getName();

        MyThread myThread3 = new MyThread();
        myThread3.start();
        String run3Name = myThread3.getName();

        System.out.println("线程1名称:" + run1Name);
        System.out.println("线程2名称:" + run2Name);
        System.out.println("线程3名称:" + run3Name);
    }

}
控制台输出:
线程1名称:Thread-0
线程2名称:Thread-1
线程3名称:Thread-2

currentThread()方法

public class MyThread extends Thread {

    @Override
    public void run() {
        // 此线程要执行的任务
        System.out.println(Thread.currentThread());
    }

}
public class Demo02MyThread {

    public static void main(String[] args) {
        MyThread myThread1 = new MyThread();
        myThread1.start();

        MyThread myThread2 = new MyThread();
        myThread2.start();

        MyThread myThread3 = new MyThread();
        myThread3.start();
    }

}
控制台输出:
Thread[Thread-0,5,main]
Thread[Thread-2,5,main]
Thread[Thread-1,5,main]

了解一下setName()方法:设置线程的名称

public class Demo03MyThread {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.setName("李华");
        myThread.start();
    }
}

控制台输出:
Thread[李华,5,main]

sleep()方法

public class MyThread2 extends Thread {
    @Override
    public void run() {
        // 此线程要执行的任务
        for (int i = 0; i < 11; i++) {
            try {
                // 参数为毫秒
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.print("第" + i  + "秒    ");
        }
    }
}
public class Demo01MyThread2 {
    public static void main(String[] args) {
        MyThread2 thread2 = new MyThread2();
        thread2.start();
    }
}
控制台输出:
第0秒    第1秒    第2秒    第3秒    第4秒    第5秒    第6秒    第7秒    第8秒    第9秒    第10秒    

创建多线程的第二种方式

实现Runnable接口,来创建多线程。

实现步骤

  1. 创建一个 Runnable接口的实现类。
  2. 在实现类中重写 Runnable接口的run方法,设置线程任务。
  3. 创建一个 Runnable接口的实现类对象。
  4. 创建Thread类对象,构造方法中传递 Runnable接口的实现类对象。
  5. 调用 Threads类中的 start方法,开启新的线程执行run方法

举例

// 创建一个 Runnable接口的实现类。
public class MyRunnable implements Runnable {
    @Override
    public void run() {
        // 在实现类中重写 Runnable接口的run方法,设置线程任务。
        for (int i = 0; i < 3; i++) {
            System.out.println(Thread.currentThread().getName() + " ~~~~~~~~~ " + i);
        }
    }
}
public class DemoRunnable {
    public static void main(String[] args) {
        // 创建一个 Runnable接口的实现类对象。
        MyRunnable myRunnable = new MyRunnable();

        // 创建Thread类对象,构造方法中传递 Runnable接口的实现类对象。
        Thread thread = new Thread(myRunnable);

        // 调用 Threads类中的 start方法,开启新的线程执行run方法
        thread.start();

        // main方法线程
        for (int i = 0; i < 3; i++) {
            System.out.println(Thread.currentThread().getName() + " ~~~~~~~~~ " + i);
        }
    }
}
控制台输出:
main ~~~~~~~~~ 0
Thread-0 ~~~~~~~~~ 0
main ~~~~~~~~~ 1
Thread-0 ~~~~~~~~~ 1
Thread-0 ~~~~~~~~~ 2
main ~~~~~~~~~ 2

使用Runnable相比Thread有哪些优势

  1. 适合多个相同的程序代码的线程去共享同一个资源。
  2. 可以避兔Java中的单继承的局限性。
  3. 増加程序的健壮性,实现解耦(把设置线程任务和开启线程分开)操作,代码可以被多个线程共享,代码和线程独立。
  4. 线程池只能放入实现 Runable或 Callable类线程,不能直接放入继承 Thread的类。

内部类实现创建多线程

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        // 在实现类中重写 Runnable接口的run方法,设置线程任务。
        for (int i = 0; i < 3; i++) {
            System.out.println(Thread.currentThread().getName() + " ~~~~~~~~~ " + i);
        }
    }
}
public class DemoSimpleThread {
    public static void main(String[] args) {
        // 创建一个 Runnable接口的实现类对象。
        MyRunnable myRunnable = new MyRunnable();

        new Thread(myRunnable) {
            @Override
            public void run() {
                System.out.print("匿名内部类的方式实现多线程的创建:");
                System.out.println(Thread.currentThread().getName() + "线程");
            }
        }.start();

        // main线程
        System.out.println("main线程");
    }
}
控制台输出:
main线程
匿名内部类的方式实现多线程的创建:Thread-0线程

原文地址:https://www.cnblogs.com/liyihua/p/12209652.html

时间: 2024-11-03 21:41:09

理解 Java 多线程的相关文章

更好的理解java多线程

1.线程的创建 之前知道Java中一个多线程的创建方法是继承Thread类或者实现Runable接口,但是看不懂下面这种创建线程的方法 第一种 [java] view plain copy print? new Thread(new Runnable() { @Override public void run() { } } }).start();//这种方式中new Thread()是创建了一个线程,而new Runable()对象中是线程想要执行的代码,这样把想要执行的代码放到一个创建的对象

对JAVA多线程 并发编程的理解

对JAVA多线程并发编程的理解 Java多线程编程关注的焦点主要是对单一资源的并发访问,本文从Java如何实现支持并发访问的角度,浅析对并发编程的理解,也算是对前段时间所学的一个总结. 线程状态转换 Java语言定义了5中线程状态,在任何一个时间点,一个线程只能有且只有其中一种状态,这5中状态分别是: ?  新建(New):创建后尚未启动的线程处于这种状态 ?  运行(Runable):Runable包括了操作系统线程状态中的Running和Ready,也就是处于此状态的线程可能正在执行,也有可

《Java多线程编程核心技术》推荐

写这篇博客主要是给猿友们推荐一本书<Java多线程编程核心技术>. 之所以要推荐它,主要因为这本书写得十分通俗易懂,以实例贯穿整本书,使得原本抽象的概念,理解起来不再抽象. 只要你有一点点Java基础,你就可以尝试去阅读它,相信定会收获甚大! 博主之前网上找了很久都没完整pdf电子版的,只有不全的试读版,这里博主提供免费.清晰.完整版供各位猿友下载: http://download.csdn.net/detail/u013142781/9452683 刚刚已经提到,<Java多线程编程核

最全面的Java多线程用法解析

最全面的java多线程用法解析,如果你对Java的多线程机制并没有深入的研究,那么本文可以帮助你更透彻地理解Java多线程的原理以及使用方法. 1.创建线程 在Java中创建线程有两种方法:使用Thread类和使用Runnable接口.在使用Runnable接口时需要建立一个Thread实例.因此,无论是通过Thread类还是Runnable接口建立线程,都必须建立Thread类或它的子类的实例.Thread构造函数: public Thread( ); public Thread(Runnab

基于JVM原理JMM模型和CPU缓存模型深入理解Java并发编程

许多以Java多线程开发为主题的技术书籍,都会把对Java虚拟机和Java内存模型的讲解,作为讲授Java并发编程开发的主要内容,有的还深入到计算机系统的内存.CPU.缓存等予以说明.实际上,在实际的Java开发工作中,仅仅了解并发编程的创建.启动.管理和通信等基本知识还是不够的.一方面,如果要开发出高效.安全的并发程序,就必须深入Java内存模型和Java虚拟机的工作原理,从底层了解并发编程的实质:更进一步地,在现今大数据的时代,要开发出高并发.高可用.考可靠的分布式应用及各种中间件,更需要深

从JAVA多线程理解到集群分布式和网络设计的浅析

对于JAVA多线程的应用非常广泛,现在的系统没有多线程几乎什么也做不了,很多时候我们在何种场合如何应用多线程成为一种首先需要选择的问题,另外关于java多线程的知识也是非常的多,本文中先介绍和说明一些常用的,在后续文章中如果有必要再说明更加复杂的吧,本文主要说明多线程的一下几个内容: 1.在应用开发中什么时候选择多线程? 2.多线程应该注意些什么? 3.状态转换控制,如何解决死锁? 4.如何设计一个具有可扩展性的多线程处理器? 5.多线程联想:在多主机下的扩展-集群? 6.WEB应用的多线程以及

(转载)Java多线程入门理解

转载出处http://blog.csdn.net/evankaka 写在前面的话:此文只能说是java多线程的一个入门,其实Java里头线程完全可以写一本书了,但是如果最基本的你都学掌握好,又怎么能更上一个台阶呢?如果你觉得此文很简单,那推荐你看看Java并发包的的线程池(Java并发编程与技术内幕:线程池深入理解),或者看这个专栏:Java并发编程与技术内幕.你将会对Java里头的高并发场景下的线程有更加深刻的理解. 目录(?)[-] 一扩展javalangThread类 二实现javalan

synchronized与static synchronized 的差别、synchronized在JVM底层的实现原理及Java多线程锁理解

本Blog分为例如以下部分: 第一部分:synchronized与static synchronized 的差别 第二部分:JVM底层又是怎样实现synchronized的 第三部分:Java多线程锁,源码剖析 第一部分:synchronized与static synchronized的差别 1.synchronized与static synchronized 的差别 synchronized是对类的当前实例进行加锁,防止其它线程同一时候訪问该类的该实例的全部synchronized块.注意这里

synchronized与static synchronized 的区别、synchronized在JVM底层的实现原理及Java多线程锁理解

本Blog分为如下部分: 第一部分:synchronized与static synchronized 的区别 第二部分:JVM底层又是如何实现synchronized的 第三部分:Java多线程锁,源代码剖析 第一部分:synchronized与static synchronized的区别 1.synchronized与static synchronized 的区别 synchronized是对类的当前实例进行加锁,防止其他线程同时访问该类的该实例的所有synchronized块,注意这里是"类