线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪阻塞运行三种基本状态。就绪状态是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机;运行状态是指线程占有处理机正在运行;阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。

  这一节介绍线程的启动方式及Thread类。

一、线程的启动方式

1、通过Thread类启动

public class ThreadTest extends Thread {

    private String name;

    public ThreadTest(String name) {
this.name = name;
} @Override
public void run() {
for(int i = 0; i < 100; i++)
System.out.println(name + " thread : " + i);
} public static void main(String[] args) {
ThreadTest tt1 = new ThreadTest("tt1");
tt1.start();//使该线程开始执行;Java 虚拟机调用该线程的 run 方法
ThreadTest tt2 = new ThreadTest("tt2");
tt2.start();
}
}

  注意:线程是通过start的方法启动的,run方法是用来实现逻辑的。

2、通过Runnable接口启动

public class RunnableTest implements Runnable {

    private String name;

    public RunnableTest(String name) {
this.name = name;
} public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(name + " runnabel : " + i);
}
} public static void main(String[] args) {
RunnableTest rt1 = new RunnableTest("rt1");
Thread t1 = new Thread(rt1);
t1.start();
RunnableTest rt2 = new RunnableTest("rt2");
Thread t2 = new Thread(rt2);
t2.start();
}
}

3、使用ExecutorService、Callable、Future实现有返回结果的多线程

public class ExcuteTest {

    public static void main(String[] args) {
System.out.println("----程序开始运行----"); int taskSize = 5;
// 创建一个线程池
ExecutorService pool = Executors.newFixedThreadPool(taskSize);
// 创建多个有返回值的任务
List<Future> list = new ArrayList<Future>();
for (int i = 1; i < taskSize + 1; i++) {
Callable c = new MyCallable(i + " ");
// 执行任务并获取Future对象
Future f = pool.submit(c);
list.add(f);
}
// 关闭线程池
pool.shutdown(); // 获取所有并发任务的运行结果
try {
for (Future f : list) {
// 从Future对象上获取任务的返回值,并输出到控制台
System.out.println("executor" + f.get().toString());
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} }
} class MyCallable implements Callable<Object> {
private String name; MyCallable(String name) {
this.name = name;
} public Object call() {
for (int i = 0; i < 100; i++) {
System.out.println(name + " : " + i);
}
return name + " end";
} }

二、Thread介绍

public class ThreadTest extends Thread {

    private String name;

    public ThreadTest(String name) {
this.name = name;
} @Override
public void run() {
System.out.println("返回当前线程的线程组中活动线程的数目 " + name + " : " + Thread.activeCount());
System.out.println("返回对当前正在执行的线程对象的引用 " + name + " : " + Thread.currentThread());
try {
for (int i = 0; i < 100; i++) {
Thread.currentThread().sleep(1);
System.out.println(name + " thread : " + i);
//Thread.currentThread().interrupt();//中断线程
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} public static void main(String[] args) {
ThreadTest tt1 = new ThreadTest("tt1");
tt1.setName("t1");//改变线程名称,使之与参数 name 相同
tt1.start();//使该线程开始执行;Java 虚拟机调用该线程的 run 方法 System.out.println("返回该线程的标识符 tt1 : " + tt1.getId());
System.out.println("返回该线程的名称 tt1 : " + tt1.getName());
System.out.println("返回线程的优先级 tt1 : " + tt1.getPriority());
System.out.println("返回该线程的状态 tt1 : " + tt1.getState()); System.out.println("测试线程是否处于活动状态 tt1 : " + tt1.isAlive());
System.out.println("测试当前线程是否已经中断 tt1 : " + tt1.isInterrupted());
System.out.println("测试该线程是否为守护线程 tt1 : " + tt1.isDaemon()); ThreadTest tt2 = new ThreadTest("tt2");
tt2.setName("t2");
System.out.println("返回线程的优先级 tt2 : " + tt2.getPriority());
tt1.yield();//暂停当前正在执行的线程对象,并执行其他线程
try {
//tt1.join();//等待该线程终止
tt1.join(10);//等待该线程终止的时间最长为 millis 毫秒
//tt1.join(10, 10);//等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒
} catch (InterruptedException e) {
e.printStackTrace();
}
tt2.start();
}
}

三、Thread与Runnable的区别

1、Runnable方式可以避免Tread方式由于java单继承特性带来的缺陷。Runnable的代码可以被多个线程(Thread实例)共享,适合于多个线程处理同一资源的情况。如下

public class TreadAndRunnable {

    public static void main(String[] args) {
//会输出15行,每个线程都分配了一个count
ThreadTest tt1 = new ThreadTest("线程1");
ThreadTest tt2 = new ThreadTest("线程2");
ThreadTest tt3 = new ThreadTest("线程3");
tt1.start();
tt2.start();
tt3.start(); //会输出5行,count被3个线程共享
RunnableTest rt = new RunnableTest();
Thread t1 = new Thread(rt, "线程1");
Thread t2 = new Thread(rt, "线程2");
Thread t3 = new Thread(rt, "线程3");
t1.start();
t2.start();
t3.start();
} } class ThreadTest extends Thread { private int count = 5;
private String name; public ThreadTest(String name) {
this.name = name;
} @Override
public void run() {
while (count > 0) {
count--;
System.out.println(name + " 剩余 : " + count);
}
}
} class RunnableTest implements Runnable{ private int count = 5; public void run() {
while (count > 0) {
count--;
System.out.println(Thread.currentThread().getName() + " 剩余 : " + count);
}
}
}

四、线程的生命周期

  就绪:创建线程对象后,调用了线程的start()方法(此时线程只是进入了线程队列,等待获取CPU服务,具备了运行条件,但并没有开始运行)

  运行:处于就绪状态的线程,一旦获取了CPU资源,便进入到运行状态,开始执行run()方法里面的逻辑

  终止:线程的run()方法执行完毕,或者线程调用了stop()方法,线程便进入终止状态。

  阻塞:一个正在执行的线程在某些情况下,由于某种原因而暂时让出了CPU资源,暂停了自己的执行,便进入了阻塞状态,如调用了sleep()方法。

五、线程的分类

用户线程:运行在前台,执行具体任务

守护线程:运行在后台,为其他前台线程服务。一旦所有用户线程都结束运行,守护线程会随JVM一起结束工作(如数据库连接池中的监测线程,JVM启动后的检测线程)

  守护线程的设置,必须在start()方法前调用setDaemon(true)设置当前线程为守护线程,否则会抛出IllegalThreadStateException异常;守护线程中产生的线程也是守护线程;不是所有的任务都可以分配给守护线程来执行如读写,计算逻辑等(因为守护线程会在用户线程结束后结束)。

jstack工具:(是window自带工具,在命令行直接可以使用)

  作用:生成JVM当前时刻线程快照,即当前进程所有线程消息。

  目的:帮助定位程序问题出现的原因,如长时间停顿、CPU占用率过高等。

  使用:在命令行输入jstack pid(进程id,在任务管理器中可以查看到)

JAVA多线程实现的三种方式

Java总结篇系列:Java多线程(一)

java从基础知识(十)java多线程(上)的更多相关文章

  1. 什么才是java的基础知识?

    近日里,很多人邀请我回答各种j2ee开发的初级问题,我无一都强调java初学者要先扎实自己的基础知识,那什么才是java的基础知识?又怎么样才算掌握了java的基础知识呢?这个问题还真值得仔细思考. ...

  2. JAVA相关基础知识

    JAVA相关基础知识 1.面向对象的特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分, ...

  3. Java SE 基础知识(一)

    一.基础知识 1. Java SE : Java Standard Edition Java ME : Java Micro Edition Java EE : Java Enterprise Edi ...

  4. java必备基础知识(一)

    学习的一点建议: 每一门语言的学习都要从基础知识开始,学习是一个过程,"万丈高楼平地起",没有一个好的地基,想必再豪华的高楼大厦终究有一天会倒塌.因此,我们学习知识也要打牢根基,厚 ...

  5. java部分基础知识整理----百度脑图版

    近期发现,通过百度脑图可以很好的归纳总结和整理知识点,本着学习和复习的目的,梳理了一下java部分的知识点,不定期更新,若有不恰之处,请指正,谢谢! 脑图链接如下:java部分基础知识整理----百度 ...

  6. Java基础知识强化之多线程笔记01:多线程基础知识(详见Android(java)笔记61~76)

    1. 基础知识: Android(java)学习笔记61:多线程程序的引入    ~    Android(java)学习笔记76:多线程-定时器概述和使用 

  7. Java基础知识强化之多线程笔记06:Lock接口 (区别于Synchronized块)

    1. 简介 我们讲到了如何使用关键字synchronized来实现同步访问.本文我们继续来探讨这个问题,从Java 5之后,在java.util.concurrent.locks包下提供了另外一种方式 ...

  8. Java基础知识强化之多线程笔记05:Java程序运行原理 和 JVM的启动是多线程的吗

    1. Java程序运行原理:     Java 命令会启动Java 虚拟机,启动 JVM,等于启动了一个应用程序,也就是启动了一个进程.该进程会自动启动一个 “主线程” ,然后主线程去调用某个类的 m ...

  9. Java的基础知识一

    一.什么是 Java 技术?为何需要 Java? Java 是由 Sun Microsystems 在 1995 年首先发布的编程语言和计算平台.有许多应用程序和 Web 站点只有在安装 Java 后 ...

随机推荐

  1. WinCE项目应用之车载导航

    WinCE车载导航系统是我过去几年投入精力比较多的一个项目.我的主要工作内容是BSP的移植.硬件模块的调试和WinCE系统的深度定制.如TDA7415驱动.TDA7415均衡器.慧翰车载蓝牙模块.华为 ...

  2. Doctype作用?严格模式与混杂模式如何区分?它们有何意义?

    怪异模式和严格模式(译注:一般称为标准模式:Standards Mode,下文中的严格模式都可以理解为标准模式)是浏览器解析CSS时的两种‘模式’.这篇文章将简单阐述这两种模式之间的差异. 译注:一个 ...

  3. vi安装Vundle+YouCompleteMe+注释快捷'scrooloose/nerdcommenter'

    Vundle is short for Vim bundle and is a Vim plugin manager. 从git上下载vundle $ git clone https://github ...

  4. [LeetCode] Binary Tree Right Side View 二叉树的右侧视图

    Given a binary tree, imagine yourself standing on the right side of it, return the values of the nod ...

  5. mac 多php版本安装

    mac上自带又apache和php. 自带的php缺少一些扩展(freeType),安装起来因为mac本身有一些sudo su都不可触及的权限,所以决定不动系统本身php,再装一个新的php不同版本. ...

  6. go reflect

    package main import ( "fmt" "reflect" // 反射包 ) type User struct{ //结构体类型 Id int ...

  7. 【WPF】整个自定义按钮后台添加

  8. Webpack:前端资源模块化管理和打包工具

    一.介绍: Webpack 是当下最热门的前端资源模块化管理和打包工具.它可以将许多松散的模块按照依赖和规则打包成符合生 产环境部署的前端资源.还可以将按需加载的模块进行代码分隔,等到实际需要的时候再 ...

  9. Error 1606 Could Not Access Network Location %SystemDrive%/inetpub/wwwroot/ 的错误解决方法

    在卸载或者重安装Infragistics NetAdvantage时候提示如标题的错误 win7下 1.打开注册表 Regedit 2.找到HKEY_LOCAL_MACHINE/SOFTWARE/Mi ...

  10. C#-WebForm-★内置对象简介★Request-获取请求对象、Response相应请求对象、Session全局变量(私有)、Cookie全局变量(私有)、Application全局公共变量、ViewState

    内置对象: 1.Request - 获取请求对象 用法:接收传值 protected void Page_Load(object sender, EventArgs e) { TextBox1.Tex ...