方式

  • 继承Thread类
  • 实现Runnable方法

实例

#继承Thread类

public class ThreadTest2 extends Thread {
private int threadCnt = 10; @Override
public void run() {
while (true) {
if (threadCnt > 0) {
System.out.println(Thread.currentThread().getName() + " 剩余个数 " + threadCnt);
threadCnt--;
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
break;
}
}
} public static void main(String[] args) {
new ThreadTest2().start();
new ThreadTest2().start();
}
}

执行

Thread-1 剩余个数 10
Thread-0 剩余个数 10
Thread-0 剩余个数 9
Thread-1 剩余个数 9
Thread-0 剩余个数 8
Thread-1 剩余个数 8
Thread-0 剩余个数 7
Thread-1 剩余个数 7
Thread-1 剩余个数 6
Thread-0 剩余个数 6
Thread-1 剩余个数 5
Thread-0 剩余个数 5
Thread-1 剩余个数 4
Thread-0 剩余个数 4
Thread-1 剩余个数 3
Thread-0 剩余个数 3
Thread-0 剩余个数 2
Thread-1 剩余个数 2
Thread-0 剩余个数 1
Thread-1 剩余个数 1

#实现Runnable方法

public class RunnalbleTest2 implements Runnable {
private int threadCnt = 10; @Override
public void run() {
while (true) {
if (threadCnt > 0) {
System.out.println(Thread.currentThread().getName() + " 剩余个数 " + threadCnt);
threadCnt--;
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
break;
}
}
} public static void main(String[] args) {
RunnalbleTest2 runnalbleTest2 = new RunnalbleTest2();
new Thread(runnalbleTest2).start();
new Thread(runnalbleTest2).start();
new Thread(runnalbleTest2).start();
new Thread(runnalbleTest2).start();
}
}

执行

Thread-0 剩余个数 10
Thread-1 剩余个数 10
Thread-2 剩余个数 8
Thread-3 剩余个数 7
Thread-1 剩余个数 6
Thread-3 剩余个数 5
Thread-2 剩余个数 6
Thread-0 剩余个数 6
Thread-1 剩余个数 2
Thread-0 剩余个数 2
Thread-2 剩余个数 2
Thread-3 剩余个数 2

可以看出该实例中虽然是2个线程,但操作的threadCnt却是一个,实现了资源共享。

比较

实现接口的方式比继承类的方式更灵活,也能减少程序之间的耦合度,面向接口编程也是设计模式6大原则的核心

start()方法和run()方法区别

涉及到线程的几个状态

新建状态:使用 new 关键字和 Thread 类(或其子类)建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。

就绪状态:当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。

运行状态:如果就绪状态的线程获取到 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。

区别

只有调用了start()方法,才会表现出多线程的特性,不同线程的run()方法里面的代码交替执行。如果只是调用run()方法,那么代码还是同步执行的,必须等待一个线程的run()方法里面的代码全部执行完毕之后,另外一个线程才可以执行其run()方法里面的代码。测试如下

package com.jihite.helloworld.thread;

public class TestNoStart {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread() {
@Override
public void run() {
pong(1);
try {
Thread.sleep(7000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread t2 = new Thread() {
@Override
public void run() {
pong(2);
try {
Thread.sleep(7000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t1.start();
t2.start();
// t1.run();
// t2.run(); System.out.println("ping~~~~");
}
static void pong(int i) {
System.out.println("pong~" + i);
}
}

参考

Java 多线程编程

40个Java多线程问题总结

Java创建线程的两种方式的更多相关文章

  1. java创建线程的两种方式及源码解析

    创建线程的方式有很多种,下面我们就最基本的两种方式进行说明.主要先介绍使用方式,再从源码角度进行解析. 继承Thread类的方式 实现Runnable接口的方式 这两种方式是最基本的创建线程的方式,其 ...

  2. 当阿里面试官问我:Java创建线程有几种方式?我就知道问题没那么简单

    这是最新的大厂面试系列,还原真实场景,提炼出知识点分享给大家. 点赞再看,养成习惯~ 微信搜索[武哥聊编程],关注这个 Java 菜鸟. 昨天有个小伙伴去阿里面试实习生岗位,面试官问他了一个老生常谈的 ...

  3. 【java并发】传统线程技术中创建线程的两种方式

    传统的线程技术中有两种创建线程的方式:一是继承Thread类,并重写run()方法:二是实现Runnable接口,覆盖接口中的run()方法,并把Runnable接口的实现扔给Thread.这两种方式 ...

  4. Java并发基础01. 传统线程技术中创建线程的两种方式

    传统的线程技术中有两种创建线程的方式:一是继承Thread类,并重写run()方法:二是实现Runnable接口,覆盖接口中的run()方法,并把Runnable接口的实现扔给Thread.这两种方式 ...

  5. 创建线程的两种方式比较Thread VS Runnable

    1.首先来说说创建线程的两种方式 一种方式是继承Thread类,并重写run()方法 public class MyThread extends Thread{ @Override public vo ...

  6. Java新建线程的两种方式

    Java新建线程有两种方式,一种是通过继承Thread类,一种是实现Runnable接口,下面是新建线程的两种方式. 我们假设有个竞赛,有一个选手A做俯卧撑,一个选手B做仰卧起坐.分别为两个线程: p ...

  7. Java创建线程的四种方式

    Java创建线程的四种方式 1.继承Thread类创建线程 定义Thread类的子类,并重写该类的run方法,run()方法的内容就是该线程执行的内容 创建Thread子类的实例,即创建了线程对象. ...

  8. Java中创建线程的两种方式

    创建线程的第一种方式: 创建一个类继承Thread 重写Thread中的run方法 (创建线程是为了执行任务 任务代码必须有存储位置,run方法就是任务代码的存储位置.) 创建子类对象,其实就是在创建 ...

  9. Java并发编程:Java创建线程的三种方式

    目录 引言 创建线程的三种方式 一.继承Thread类 二.实现Runnable接口 三.使用Callable和Future创建线程 三种方式的对比 引言 在日常开发工作中,多线程开发可以说是必备技能 ...

随机推荐

  1. STL其他--<tuple>用法【C11】

     tuple 库 tuple 库 是能够将不同类型的对象组合起来形成一个对象.和pair 对象一样,但是可以组织多种不同类型的元素. tuple中的元素类型是在编译时期决定的.与<utility ...

  2. Hadoop读写流程

    写流程 读流程 HDFS写数据流程 HDFS读数据流程 网络拓扑-节点距离计算 节点距离:两个节点到达最近的共同祖先的距离总和

  3. Delphi7调用DelphiXE编写的DLL问题

    http://bbs.csdn.net/topics/380045353 用DelphiXE在WIN2008下编写一个访问WebServices的DLL ws.dll,只有一个输出函数,如下: fun ...

  4. ABP框架入门踩坑-配置数据库表前缀

    配置数据库表前缀 ABP踩坑记录-目录 本篇其实和ABP关系并不大,主要是EF Core的一些应用-.-. 起因 支持数据库表前缀应该是很多应用中比较常见的功能,而在ABP中并没直接提供这一功能,所以 ...

  5. Ubuntu系统常见问题解决

    我本人使用Ubuntu16.04LTS已经有一段时间了.实话来说,ubuntu虽然确实是开源世界的一款优秀的桌面操作系统,但是易用性和稳定性相比Windows还是差太多.本人从安装系统到逐步配置生产环 ...

  6. python收集jvm数据

    之前前辈用 java 写的收集 jvm 脚本, 不太方便组内小伙伴维护, 遂用 python 重写了 #!/usr/bin/env python # -*- coding: utf-8 -*- # F ...

  7. Linux 中指定启动 tomcat 的 jdk 版本

    环境: RHEL6.5. tomcat8.5.jdk1.8.0_181 修改 catalina.sh.setclasspath.sh 文件 进入目录 $ cd /data01/server/apach ...

  8. vue项目axios请求接口,后端代理请求接口404,问题出现在哪?

    在vue项目中,列表数据需要用到qq音乐接口中的数据,但是直接请求不行,有host及referer限制,需要采用后端代理的方式.借助axios及node的express,在dev-server.js中 ...

  9. 移动端测试接口--Fiddler抓包工具

    Fiddler抓包工具是一款免费且功能强大的数据包抓取软件.它通过代理的方式获取程序http通讯的数据,可以用其检测网页和服务器的交互情况,能够记录所有客户端和服务器间的http请求,支持监视.设置断 ...

  10. Celery -- 分布式任务队列 及实例

    Celery 使用场景及实例 Celery介绍和基本使用 在项目中如何使用celery 启用多个workers Celery 定时任务 与django结合 通过django配置celery perio ...