美文网首页
【Java学习】多线程入门|创建线程|实现线程同步

【Java学习】多线程入门|创建线程|实现线程同步

作者: 榆野铃爱 | 来源:发表于2019-08-18 20:32 被阅读0次

心得感悟

多线程的基本概念还是很容易理解的,以前只知道软件可以同时运行,今天终于了解了它的实现机制,还是有点意思的。多线程入门是比较简单,进门后再往前走那就有点难了,所以今天先不讲线程安全。


内容简概

  • 一、多线程介绍
  • 二、多线程的状态和生命周期
  • 三、为什么要创建⼦线程
  • 四、创建线程的两种⽅式
  • 五、实现线程同步的两种方式

具体内容

一、多线程介绍

再说线程之前,我们先来了解一下进程。什么是进程呢?进程就是正在运行的程序。你可以按下Ctrl + Shift + ESC键调出任务管理器,里面会显示出当前正在运行的进程(见图一)。应用名称最后的小括号内的数字表示当前进程包含的线程个数,你也可以展开列表查看具体的线程(见图二)。

一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。

拿下载文件、视频举例,当你要下载多个文件或视频时,若是单线程,只有当一个下载任务执行完后,才能执行另一个下载任务;若是多线程,可以多个下载任务“同时”执行,这样大大提高了程序的运行效率,让CPU的使用率更高。

图一:任务管理器
图二:具体的线程

二、多线程的状态和生命周期

状态名              定义
创建状态(new) 准备好了一个多线程的对象,即执行了new Thread(); 创建完成后就需要为线程分配内存
就绪状态(runnable) 调用了start()方法, 等待CPU进行调度
运行状态(running) 执行run()方法
阻塞状态(blocked) 暂时停止执行线程,将线程挂起(sleep()、wait()、join()、没有获取到锁都会使线程阻塞), 可能将资源交给其它线程使用
死亡状态(terminated) 线程销毁(正常执行完毕、发生异常或者被打断interrupt()都会导致线程终止)
多线程的生命周期

三、为什么要创建⼦线程

如果在主线程中存在比较耗时的操作,如下载视频、数据处理,这些操作会阻塞主线程,后面的任务必须等这些任务执行完后才能执行。为了不阻塞主线程,需要将耗时的任务放在子线程中去处理。

四、创建线程的两种⽅式

1. 第一种方式:Thread

写一个类,使它继承Thread

class TestThread extends Thread{

    // 写一个类继承Thread
    // 实现run方法
    // 方法里面是具体要执行的代码
    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(name);
        for (int i =1 ; i <= 100; i++) {
            System.out.println(name + ":" +i);
        }
        super.run();
    }
}

使用方式:使用Thread操作这个任务,然后用setName()给进程命名,用start()开始进程。

        Thread t = new Thread(pt);
        t.setName("子线程1");
        t.start();
2. 第二种方式:Runnable

写一个类,使它实现Runnable接⼝

class MyThread implements Runnable{
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}

使用方式①:使用Thread操作这个任务,然后用setName()给进程命名,用start()开始进程。

        Thread t = new Thread(mt);
        t.setName("子线程1");
        t.start();

使用方式②:使用匿名对象,然后直接在run()中写入执行语句,同样用setName()给进程命名,用start()开始进程。这个方式仅适用于只使用一次这个任务的情况。

        Thread t = new Thread(new Runnable() {
           @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName()+":"+i);
                }
            }
        });
        t.setName("子线程3");
        t.start();

使用方式③:创建线程的同时直接开启线程任务,不需要操作线程对象本身,但是无法为这个进程命名。

        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName()+";"+i);
                }
            }
        }).start();

使用方式④:使用Lambda表达式,但事实不建议使用,因为阅读性差。

      new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName()+";"+i);
            }
        }).start();

五、实现线程同步的两种方式

1. 第一种方式:synchronized

使⽤synchronized同步代码块。我们写一个卖火车票的程序。

public class lock {
    public static void main(String[] args){
        Ticket ticketCQ = new Ticket("重庆");
        Thread t1 = new Thread(ticketCQ);
        t1.start();

        Ticket ticketSH = new Ticket("上海");
        Thread t2 = new Thread(ticketSH);
        t2.start();
    }
}

class Ticket implements Runnable{
    //定义所有车票的数量
    public static int num = 100;
    String name;

    //定义
    public Ticket(String name){
        this.name = name;
    }

    static final Object obj = new Object();

    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            // 判断有没有票
            synchronized (obj){
                // 需要同步的代码
                if (num > 0) {
                    System.out.println(name + "出票:" + num);
                    num--;
                }
                else {
                    break;
                }
            }
        }
    }
}

也可以用同步方法实现,同步方法的本质其实就是同步代码块。只需将部分代码改为如下代码即可。

@Override
    public void run() {
        synchronized (this){
            test();
        }
    }

    public synchronized void test() {
        for (int i = 1; i <= 100; i++) {
            // 判断有没有票
            synchronized (obj){
                // 需要同步的代码
                if (num > 0) {
                    System.out.println(name + "出票:" + num);
                    num--;
                }
                else {
                    break;
                }
            }
        }
    }
2. 第二种方式:ReentrantLock

使⽤ReentrantLock同步

class Ticket implements Runnable{

    //定义所有车票的数量
    public static int num = 100;
    String name;

    //定义
    public Ticket(String name){
        this.name = name;
    }

    //创建一个可重复的锁
    static ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            // 判断有没有票

                // 加锁
                lock.lock();
                //需要同步的代码
                if (num > 0) {
                    System.out.println(name + "出票:" + num);
                    num--;
                    lock.newCondition();
                }
                else {
                    break;
                }
                lock.unlock();
        }
    }
}

相关文章

  • 5月份第一周学习安排

    学习内容: java多线程及线程同步的方法(使用) java多线程各种同步方法的原理和优缺点 java多线程设计模...

  • 【Java学习】多线程入门|创建线程|实现线程同步

    心得感悟 多线程的基本概念还是很容易理解的,以前只知道软件可以同时运行,今天终于了解了它的实现机制,还是有点意思的...

  • Java进阶之synchronized关键字详解

    掌握多线程是从Java入门后需要跳过的第一大坎,使用多线程就难以避免要处理数据同步问题,在Java多线程中实现数据...

  • Java基础(六)

    多线程 Java多线程并发 1.1 JAVA 并发知识库 1.2 JAVA 线程实现/创建方式 1.2.1 继承 ...

  • 蚂蚁Java互联网架构师第1期高端

    教程目录 ├─0001-多线程快速入门.zip ├─0002-多线程之间实现同步.zip ├─0003--多线程之...

  • Android中的多线程

    1. Java多线程基础 Java多线程,线程同步,线程通讯 2. Android常用线程 HandlerThre...

  • [C# 线程处理系列]专题四:线程同步

    目录: 一、线程同步概述 二、线程同步的使用 三 、总结 一、线程同步概述 前面的文章都是讲创建多线程来实现让我们...

  • 多线程

    创建一个多线程 创建多线程-继承线程类 创建多线程-实现Runnable接口 创建多线程-匿名类code

  • Python 3 多线程编程

    本文主要基于python 3.5实现多线程编程 1. 创建多线程 2. 多线程间的同步,lock机制 3. que...

  • 10.3多线程详解

    Java高级-多线程 多线程创建 多线程通讯 线程池 1.多线程创建 thread/runnable图:继承Thr...

网友评论

      本文标题:【Java学习】多线程入门|创建线程|实现线程同步

      本文链接:https://www.haomeiwen.com/subject/ycursctx.html