Java多线程基础

目录
  • 一、线程
  • 二、创建多线程的方式
    • 1、继承Thread类实现多线程
    • 2、实现Runnable接口方式实现多线程
    • 3、Callable接口创建线程
  • 三、线程的生命周期与状态
  • 四、线程的执行顺序
    • 1、定时器
    • 2、线程的互斥与同步通信
    • 3、线程同步通信技术

一、线程

什么是线程:

线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。

什么是多线程:

多线程指在单个程序中可以同时运行多个不同的线程执行不同的任务。

二、创建多线程的方式

多线程的创建方式有三种:ThreadRunnableCallable

1、继承Thread类实现多线程

      Thread thread = new Thread() {
            @Override
            public void run() {
                super.run();
                while (true) {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("1:" + Thread.currentThread().getName());
                    System.out.println("2:" + this.getName());
                }
            }
        };
        thread.start();

2、实现Runnable接口方式实现多线程

Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("3:" + Thread.currentThread().getName());
                }
            }
        });
        thread1.start();

3、Callable接口创建线程

public class CallableTest {

    public static void main(String[] args) {
        System.out.println("当前线程是:" + Thread.currentThread());
        Callable myCallable = new Callable() {
            @Override
            public Integer call() throws Exception {
                int i = 0;
                for (; i < 10; i++) {

                }
                //当前线程
                System.out.println("当前线程是:" + Thread.currentThread()
                        + ":" + i);
                return i;
            }
        };
        FutureTask<Integer> fu = new FutureTask<Integer>(myCallable);
        Thread th = new Thread(fu, "callable thread");

        th.start();

        //得到返回值
        try {
            System.out.println("返回值是:" + fu.get());

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

当前线程是:Thread[main,5,main]
当前线程是:Thread[callable thread,5,main]:10
返回值是:10

总结:

实现Runnable接口相比继承Thread类有如下优势:

  • 可以避免由于Java的单继承特性而带来的局限;
  • 增强程序的健壮性,代码能够被多个线程共享,代码与数据是独立的;
  • 适合多个相同程序代码的线程区处理同一资源的情况。

实现Runnable接口和实现Callable接口的区别:

  • Runnable是自从java1.1就有了,而Callable是1.5之后才加上去的
  • Callable规定的方法是call() , Runnable规定的方法是run()
  • Callable的任务执行后可返回值,而Runnable的任务是不能返回值是(void)
  • call方法可以抛出异常,run方法不可以
  • 运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。
  • 加入线程池运行,Runnable使用ExecutorServiceexecute方法,Callable使用submit方法。

三、线程的生命周期与状态

四、线程的执行顺序

Join线程的运行顺序

原理:

1、定时器

import java.util.Timer;
import java.util.TimerTask;

public class TraditionalTimerTest {
    public static void main(String[] args) {

//         new Timer().schedule(new TimerTask() {
//             @Override
//             public void run() {
//
//                 System.out.println("bombing!");
//             }
//         },10000);

        class MyTimberTask extends TimerTask {
            @Override
            public void run() {

                System.out.println("bombing!");
                new Timer().schedule(new MyTimberTask(), 2000);
            }
        }

        new Timer().schedule(new MyTimberTask(), 2000);

        int count = 0;
        while (true) {
            System.out.println(count++);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}

0
1
bombing!
2
3
bombing!
4
5
bombing!
6
省略...

2、线程的互斥与同步通信

public class TraditionalThreadSynchronized {

    public static void main(String[] args) {

        new TraditionalThreadSynchronized().init();
    }

    private void init() {
        final Outputer outputer = new Outputer();

        new Thread(new Runnable() {
            @Override
            public void run() {

                while (true) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    outputer.output("kpioneer");

                }
            }
        }).start();

//        new Thread(new Runnable() {
//            @Override
//            public void run() {
//
//                while (true) {
//                    try {
//                        Thread.sleep(10);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                    outputer.output2("Tom");
//
//                }
//            }
//        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {

                while (true) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    outputer.output3("Jack");

                }
            }
        }).start();
    }

  static   class Outputer {

        public void output(String name) {

            int len = name.length();

            synchronized (Outputer.class) {

                for (int i = 0; i < len; i++) {
                    System.out.print(name.charAt(i));
                }
                System.out.println();
            }

        }

        public synchronized void output2(String name) {
            int len = name.length();

            for (int i = 0; i < len; i++) {
                System.out.print(name.charAt(i));
            }
            System.out.println();
        }

      public static synchronized void output3(String name) {
          int len = name.length();

          for (int i = 0; i < len; i++) {
              System.out.print(name.charAt(i));
          }
          System.out.println();
      }
    }
}

3、线程同步通信技术

子线程循环10次,接着主线程循环100,接着又回到子线程循环10次,接着再回到主线程有循环100,如此循环50次,请写出程序。

public class TraditionalThreadCommunication {
    public static void main(String[] args) {

        final Business business = new Business();
        new Thread(new Runnable() {
                    @Override
                    public void run() {
                        for (int i = 1; i <= 50; i++) {
                            business.sub(i);
                        }
                    }
                }
        ).start();
        for (int i = 1; i <= 50; i++) {
            business.main(i);
        }
    }

}

/**
 *要用到共同数据(包括同步锁)的若干方法应该归在同一个类身上,
 * 这种设计正好体现了高类聚和和程序的健壮性
 */
class Business {
    private boolean bShouldSub = true;
    public synchronized void sub(int i) {
        if(!bShouldSub) {

            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        for (int j = 1; j <= 10; j++) {
            System.out.println("sub thread sequece of " + j + ",loop of " + i);

        }
        bShouldSub = false;
        this.notify();
    }

    public synchronized void main(int i) {
        if(bShouldSub) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        for (int j = 1; j <=100; j++) {
            System.out.println("main thread sequece of " + j + ",loop of " + i);

        }
        bShouldSub = true;
        this.notify();
    }
}

sub thread sequece of 1,loop of 1
sub thread sequece of 2,loop of 1
sub thread sequece of 3,loop of 1
sub thread sequece of 4,loop of 1
sub thread sequece of 5,loop of 1
sub thread sequece of 6,loop of 1
sub thread sequece of 7,loop of 1
sub thread sequece of 8,loop of 1
sub thread sequece of 9,loop of 1
sub thread sequece of 10,loop of 1
main thread sequece of 1,loop of 1
main thread sequece of 2,loop of 1
main thread sequece of 3,loop of 1
main thread sequece of 4,loop of 1
main thread sequece of 5,loop of 1
main thread sequece of 6,loop of 1
main thread sequece of 7,loop of 1
main thread sequece of 8,loop of 1
main thread sequece of 9,loop of 1
main thread sequece of 10,loop of 1
main thread sequece of 11,loop of 1
省略中间...
main thread sequece of 99,loop of 1
main thread sequece of 100,loop of 1
sub thread sequece of 1,loop of 2
sub thread sequece of 2,loop of 2
sub thread sequece of 3,loop of 2
sub thread sequece of 4,loop of 2
sub thread sequece of 5,loop of 2
sub thread sequece of 6,loop of 2
sub thread sequece of 7,loop of 2
sub thread sequece of 8,loop of 2
sub thread sequece of 9,loop of 2
sub thread sequece of 10,loop of 2
main thread sequece of 1,loop of 2
main thread sequece of 2,loop of 2
main thread sequece of 3,loop of 2
省略...

到此这篇关于Java多线程基础的文章就介绍到这了,更多相关Java多线程内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • java多线程模拟实现售票功能

    铁道部发布了一个售票任务,要求销售1000张票,要求有3个窗口来进行销售,请编写多线程程序来模拟这个效果. 1 线程类 测试方法: public static void main(String[] args) { MyThread t1 = new MyThread("窗口1"); MyThread t2 = new MyThread("窗口1"); MyThread t3 = new MyThread("窗口1"); t1.start(); t

  • Java多线程之搞定最后一公里详解

    目录 绪论 一:线程安全问题 1.1 提出问题 1.2 不安全的原因 1.2.1 原子性 1.2.2 代码"优化" 二:如何解决线程不安全的问题 2.1 通过synchronized关键字 2.2 volatile 三:wait和notify关键字 3.1 wait方法 3.2 notify方法 3.3 wait和sleep对比(面试常考) 四:多线程案例 4.1 饿汉模式单线程 4.2 懒汉模式单线程 4.3 懒汉模式多线程低性能版 4.4懒汉模式-多线程版-二次判断-性能高 总结

  • java多线程使用mdc追踪日志方式

    目录 多线程使用mdc追踪日志 背景 解决方案 实现 参考 多线程日志追踪 1.问题描述 2. 代理实现日志追踪 多线程使用mdc追踪日志 背景 多线程情况下,子线程的sl4j打印日志缺少traceId等信息,导致定位问题不方便 解决方案 打印日志时添加用户ID.trackId等信息,缺点是每个日志都要手动添加 使用mdc直接拷贝父线程值 实现 // 新建线程时: Map<String, String> mdcContextMap = MDC.getCopyOfContextMap() //

  • Java多线程揭秘之synchronized工作原理

    目录 一. 特性 二. 加锁过程(锁升级/锁膨胀) 1. 无锁状态 2. 偏向锁 3. 轻量级锁 4. 重量级锁 5. 总结 三. 锁优化 1. 锁消除 2. 锁粗化 在学习本篇文章时,如果有不太懂的地方,大家也可以先看看博主上一篇文章,锁的这部分内容是面试中很常见的问题,多学学对自己是非常有帮助的.同时,朋友们如果有什么问题都可以随时和我探讨,大家一起进步! 一. 特性 这部分内容在上篇文章中的 synchronized充当了哪些锁部分已经介绍过了哦,没有看的小伙伴可以去看看synchroni

  • Java多线程之并发编程的基石CAS机制详解

    目录 一.CAS机制简介 1.1.悲观锁和乐观锁更新数据方式 1.2.什么是CAS机制 1.3.CAS与sychronized比较 1.4.Java中都有哪些地方应用到了CAS机制呢? 1.5.CAS 实现自旋锁 1.6.CAS机制优缺点 1>ABA问题 2>可能会消耗较高的CPU 3>不能保证代码块的原子性 二.Java提供的CAS操作类--Unsafe类 2.1.Unsafe类简介 2.2.Unsafe类的使用 三.CAS使用场景 3.1.使用一个变量统计网站的访问量 3.2.现在我

  • 一文彻底搞懂java多线程和线程池

    目录 什么是线程 一. Java实现线程的三种方式 1.1.继承Thread类 1.2.实现Runnable接口,并覆写run方法 二. Callable接口 2.1 Callable接口 2.2 Future接口 2.3 Future实现类是FutureTask. 三. Java线程池 3.1.背景 3.2.作用 3.3.应用范围 四. Java 线程池框架Executor 4.1.类图: 4.2 核心类ThreadPoolExecutor: 4.3 ThreadPoolExecutor逻辑结

  • Java多线程之死锁详解

    目录 1.死锁 2.死锁经典问题--哲学家就餐问题 总结 1.死锁 出现场景:当线程A拥有了A对象的锁,想要去获取B对象的锁:线程B拥有了B对象的锁,想要拥有A对象的锁,两个线程在获取锁的时候,都不会释放已经持有的锁,于是,就造成了死锁. 示例代码: @Slf4j public class ThreadTest { private static Object objectA = new Object(); private static Object objectB = new Object();

  • Java 多线程之两步掌握

    目录 导论:初识多线程 一:动手来创建多线程 1.1 创建一个主线程 1.2 多线程抢占式执行 二:创建线程的几个常用方法 2.2 继承 Thread 类 2.2 实现 Runnable 接口 2.3 匿名类创建 三:Thread的几个常见属性 导论:初识多线程 首先,我们来讨论讨论什么叫做多线程.举个简单的例子,比如说造房子这个任务.如果只有一个人的话,他既要搬砖还得拎砂浆.搅拌水泥之类的(其他工种这里就不一一阐述了),哪怕这个工人技术再熟练,精力再旺盛,他同时也只能干一个工种.那么问题来了,

  • Java多线程基础

    目录 一.线程 二.创建多线程的方式 1.继承Thread类实现多线程 2.实现Runnable接口方式实现多线程 3.Callable接口创建线程 三.线程的生命周期与状态 四.线程的执行顺序 1.定时器 2.线程的互斥与同步通信 3.线程同步通信技术 一.线程 什么是线程: 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位. 什么是多线程: 多线程指在单个程序中可以同时运行多个不同的线程执行不同的任务. 二.创建多线程的方式 多线程的创建方式有三种:T

  • Java多线程——基础概念

    目录 java多线程 并发与并行: 多线程使用场景: 创建线程的方式: Thread类的有关方法: 线程的同步: 1. 同步代码块: 2. synchronized还可以放在方法声明中,表示整个方法为同步方法. 总结 java多线程 并发与并行: 并行: 指两个或多个事件在同一时刻发生 ( 同时发生 ) . 并发: 指两个或多个事件在同一个时间段内发生. 多线程使用场景: 1. 后台任务,比如游戏服务器 2.定时向大量用户(100W)用户发邮件 3.异步处理: 发微博/记录日志等 4.分布式计算

  • Java多线程基础——Lock类

    之前已经说道,JVM提供了synchronized关键字来实现对变量的同步访问以及用wait和notify来实现线程间通信.在jdk1.5以后,JAVA提供了Lock类来实现和synchronized一样的功能,并且还提供了Condition来显示线程间通信. Lock类是Java类来提供的功能,丰富的api使得Lock类的同步功能比synchronized的同步更强大.本文章的所有代码均在Lock类例子的代码 本文主要介绍一下内容: Lock类 Lock类其他功能 Condition类 Con

  • 新手了解java 多线程基础知识(二)

    目录 一.线程的生命周期 JDK中用Thread.State类定义了线程的几种状态: 二.线程同步 1.为什么要有线程同步 2.synchronized 2.1同步代码块 2.2同步方法 3.Lock锁 总结 一.线程的生命周期 JDK中用Thread.State类定义了线程的几种状态: 要想实现多线程,必须在主线程中创建新的线程对象.Java语言使用 Thread类及其子类的对象来表示线程,在它的一个完整的生命周期中通常 要经历如下的五种状态: 新建:当一个Thread类或其子类的对象被声明并

  • 新手了解java 多线程基础知识(一)

    目录 1.基本概念 2.多线程的创建 3.Thread类方法介绍 总结 1.基本概念 程序.进程.线程 程序(program)是为完成特定任务.用某种语言编写的一组指令的集 合.即指一段静态的代码,静态对象. 进程(process)是程序的一次执行过程,或是正在运行的一个程序.是 一个动态的过程:有它自身的产生.存在和消亡的过程--具有生命 周期.可以理解为一个正在运行的软件. 线程(thread),进程可进一步细化为线程,是一个程序内部的一条执行 路径.可以理解为一个软件的功能. 多线程程序的

  • java——多线程基础

    目录 多线程使用场景: 线程和进程区别: 创建线程的方式: Thread类的有关方法: 线程的同步: 模拟火车站售票程序 线程的同步:synchronized 1. 同步代码块: 2. synchronized还可以放在方法声明中,表示整个方法为同步方法. 总结 并发与并行: 并行: 指两个或多个事件在同一时刻发生 ( 同时发生 ) . 并发: 指两个或多个事件在同一个时间段内发生. 多线程使用场景: 1. 后台任务,比如游戏服务器 2.定时向大量用户(100W)用户发邮件 3.异步处理: 发微

  • java多线程:基础详解

    目录 Java内存模型 主内存和工作内存的交互命令 内存模型的原子性 内存模型的可见性 内存模型的有序性 指令重排优化的底层原理 valatile原理 volatile与加锁的区别 先行发生原则 线程的三种实现方式 总结 Java内存模型 Java内存模型与Java内存结构不同,Java内存结构指的是jvm内存分区.Java内存模型描述的是多线程环境下原子性,可见性,有序性的规则和保障. Java内存模型提供了主内存和工作内存两种抽象,主内存指的是共享区域 ,工作内存指的是线程私有工作空间. 当

  • 新手了解java 多线程基础知识

    目录 一.线程的生命周期 JDK中用Thread.State类定义了线程的几种状态: 二.线程同步 1.为什么要有线程同步 2.synchronized 2.1同步代码块 2.2同步方法 3.Lock锁 四.基本概念 五.多线程的创建 六.Thread类方法介绍 总结 一.线程的生命周期 JDK中用Thread.State类定义了线程的几种状态: 要想实现多线程,必须在主线程中创建新的线程对象.Java语言使用 Thread类及其子类的对象来表示线程,在它的一个完整的生命周期中通常 要经历如下的

  • Java多线程基础 线程的等待与唤醒(wait、notify、notifyAll)

    本篇我们来研究一下 wait() notify() notifyAll() . DEMO1: wait() 与 notify() public class Test { static class ThreadOne extends Thread { private Callback mCallback; @Override public void run() { work(); if (mCallback != null) { mCallback.onResult(false); } } //

  • Java多线程和并发基础面试题(问答形式)

    本文帮助大家掌握Java多线程基础知识来对应日后碰到的问题,具体内容如下 一.Java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用.而线程是在进程中执行的一个任务.Java运行环境是一个包含了不同的类和程序的单一进程.线程可以被称为轻量级进程.线程需要较少的资源来创建和驻留在进程中,并且可以共享进程中的资源. 2. 多线程编程的好处是什么? 在多线程程序中,多个线程被并发的执行以提高程序的效率,C

随机推荐