java从基础知识(十)java多线程(上)
线程,有时被称为轻量级进程(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的基础知识?
近日里,很多人邀请我回答各种j2ee开发的初级问题,我无一都强调java初学者要先扎实自己的基础知识,那什么才是java的基础知识?又怎么样才算掌握了java的基础知识呢?这个问题还真值得仔细思考. ...
- JAVA相关基础知识
JAVA相关基础知识 1.面向对象的特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分, ...
- Java SE 基础知识(一)
一.基础知识 1. Java SE : Java Standard Edition Java ME : Java Micro Edition Java EE : Java Enterprise Edi ...
- java必备基础知识(一)
学习的一点建议: 每一门语言的学习都要从基础知识开始,学习是一个过程,"万丈高楼平地起",没有一个好的地基,想必再豪华的高楼大厦终究有一天会倒塌.因此,我们学习知识也要打牢根基,厚 ...
- java部分基础知识整理----百度脑图版
近期发现,通过百度脑图可以很好的归纳总结和整理知识点,本着学习和复习的目的,梳理了一下java部分的知识点,不定期更新,若有不恰之处,请指正,谢谢! 脑图链接如下:java部分基础知识整理----百度 ...
- Java基础知识强化之多线程笔记01:多线程基础知识(详见Android(java)笔记61~76)
1. 基础知识: Android(java)学习笔记61:多线程程序的引入 ~ Android(java)学习笔记76:多线程-定时器概述和使用
- Java基础知识强化之多线程笔记06:Lock接口 (区别于Synchronized块)
1. 简介 我们讲到了如何使用关键字synchronized来实现同步访问.本文我们继续来探讨这个问题,从Java 5之后,在java.util.concurrent.locks包下提供了另外一种方式 ...
- Java基础知识强化之多线程笔记05:Java程序运行原理 和 JVM的启动是多线程的吗
1. Java程序运行原理: Java 命令会启动Java 虚拟机,启动 JVM,等于启动了一个应用程序,也就是启动了一个进程.该进程会自动启动一个 “主线程” ,然后主线程去调用某个类的 m ...
- Java的基础知识一
一.什么是 Java 技术?为何需要 Java? Java 是由 Sun Microsystems 在 1995 年首先发布的编程语言和计算平台.有许多应用程序和 Web 站点只有在安装 Java 后 ...
随机推荐
- L1-009. N个数求和
https://www.patest.cn/contests/gplt/L1-009 原来写的找了好久还是有一个测试点没过, 虽说是道水题,但是今天一遍就过了还是挺高兴的. 送你机组数据 52/5 4 ...
- Animator Controller 继承关系
准备知识 对于Animator Controller中蜘蛛网一样的几十条连线,后续如果靠人工维护,那成本将是很大. AnimatorOverrideController组件的文档:https://do ...
- 杂项之使用qq邮箱发送邮件
杂项之使用qq邮箱发送邮件 本节内容 特殊设置 测试代码 1. 特殊设置 之前QQ邮箱直接可以通过smtp协议发送邮件,不需要进行一些特殊的设置,但是最近使用QQ邮箱测试的时候发现以前使用的办法无法奏 ...
- iOS CALayer应用详解
跟着大神一起进步,本篇博客原文地址:http://blog.csdn.net/hello_hwc?viewmode=contents 一 CALayer是什么? Layers是绘图和动画的基础, L ...
- 华为5G空口新技术(2015年)
2015-03-24 长江后浪推前浪,4G建设方兴未艾,业界关于5G的讨论已如火如荼.对于每一代移动通信,空口技术都相当于王冠上的明珠. 在月初的世界移动通信大会上,华为发布了面向5G的新空口,并展出 ...
- 【WPF】最近在学习wpf 的绑定,,
最近在学习wpf 的绑定,,1.简单的说就是版前端和后端用自己的方法给分开了2.baseVm 模型 baseCmd 命令3.命令传参修改的只是界面里的属性,而不修改其它的值4.前端改变后端, 后端改变 ...
- python2.7初学(〇)
为什么学习Python Python为我们提供了非常完善的基础代码库,覆盖了网络.文件.GUI.数据库.文本等大量内容,被形象地称作“内置电池(batteries included)”.而且pytho ...
- 前端必备的js知识点(转载)
1.本文主体源自:http://www.cnblogs.com/coco1s/p/4029708.html,有兴趣的可以直接去那里看,也可以看看我整理加拓展的.2.js是一门什么样的语言及特点? ...
- OAuth2.0相关知识
自己总结的可能有误差. 大致分为6个步骤: 1.注册相关应用,获取client_id,client_secret.2.第三方请求用户授权.用户点击按钮同意授权后,授权服务器将生成一个用户凭证(code ...
- Android基础测试题(四)
看了前两道题大家有没有发现,测试题少了(一),大家猜猜测试题(一)是什么? Android基础测试题(四): 需求: 建一个方法,格式化输出2016-11-14 10:15:26格式的当前时间,然后截 ...