线程的创建方式有两种:

implements Runnable和extends Thread。
继承Thread类:

package com.test.threadtest;import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mThread thread = new mThread();//创建线程thread.start();//启动线程}class mThread extends Thread{@Overridepublic void run() {}}
}

这里当调用start()方法的时候就会,线程就会进入线程队列中,一旦线程获取到了CPU的时间片,线程就会执行run()方法。当run()方法执行完毕,线程就会被销毁。

实现Runnable接口:

package com.test.threadtest;import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mThread mthread = new mThread();Thread thread = new Thread(mthread);//创建线程thread.start();//启动线程}class mThread implements Runnable{@Overridepublic void run() {}}
}


两种方式的比较:

(1)Runnable方式可以避免Thread方式由于Java单继承特性带来的缺陷。
(2)Runnable的代码可以被多个线程(Thread实例)共享,适合于多个线程处理同一资源的情况。
第二不同之处的解释:
用实现Runnable接口的方式:

package com.test.threadtest;import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//创建三个线程来模拟三个售票窗口mThread mthread = new mThread();Thread thread1 = new Thread(mthread,"窗口一");//创建线程Thread thread2 = new Thread(mthread,"窗口二");//创建线程Thread thread3 = new Thread(mthread,"窗口三");//创建线程thread1.start();//启动线程thread2.start();//启动线程thread3.start();//启动线程}class mThread implements Runnable{private int ticketsCount = 5;//总共有5张票@Overridepublic void run() {while(ticketsCount>0){ticketsCount--;//Thread.currentThread():获取当前的线程System.out.println(Thread.currentThread().getName()+"卖了一张票,剩余票数为:"+ticketsCount);}}}
}

结果截图:

用继承Thread类的方式:

package com.test.threadtest;import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;public class SecondActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//创建三个线程模拟三个窗口卖票mThread mthread1 = new mThread("窗口一");mthread1.start();mThread mthread2 = new mThread("窗口二");mthread2.start();mThread mthread3 = new mThread("窗口三");mthread3.start();}class mThread extends Thread{private int ticketsCont = 5;//一共有5张火车票private String name;//窗口,也就是线程的名字public mThread(String name) {this.name = name;}@Overridepublic void run() {while(ticketsCont>0){ticketsCont--;System.out.println(name+"卖了一张票,剩余票数为:"+ticketsCont);}}}
}

结果截图:

造成这种结果差异的原因分析:
实现Runnable接口的代码中,创建的三个线程中传递的是同一个Runnable对象,所引用的是同一个资源对象。
继承Thread类的代码中,创建的三个线程对象,每个线程对象中的资源也是独立的,并不是共享的。

线程的生命周期:

从图中可以看出线程的一生中一共有5种状态,分别是:
(1)新建状态: 也就是new出一个线程对象,新建一个线程对象,如:Thread thread = new Thread();
(2)就绪状态: 创建了线程对象后,调用了线程的start()方法,此时线程只是进入了线程队列,等待获取CPU服务,具备了运行条件,但并不一定已经开始运行了。
因为这个时候CPU有可能正在执行其他的线程,而我们当前的这个线程可能要等待,当获取到了CPU服务才会进入运行状态。
(3)运行状态: 处于就绪状态的线程,一旦获取了CPU资源,便进入到运行状态,开始执行run()方法里面的逻辑。
(4)终止状态: 线程的run()方法执行完毕,或者线程调用了stop()方法,线程便进入终止状态。
(5)阻塞状态: 一个正在run()方法中执行的线程在某些情况下,由于某种原因而暂时让出了CPU资源,暂停了自己的执行,便进入了阻塞状态,如调用了sleep()方法。
也就是说,如果在run()方法中调用sleep()方法,就会休眠自己进入阻塞状态,也就会把自己所占用的CPU资源让出来,让其他线程去获取CPU资源,当休眠时间过了之后,线程就会解除阻塞状态进入就绪状态,等待获取CPU资源。

守护线程:

Java中线程有两类:
(1)用户线程:运行在前台,执行具体的任务。
如:程序的主线程,连接网络的子线程等都是用户线程
(2)守护线程:运行在后台,为其他前台的用户线程服务。
特点:
一旦所有用户线程都结束运行,守护线程会随JVM虚拟机一起结束工作。
应用:
数据库连接池中的检测线程,JVM虚拟机启动后的监测线程
最常见的守护线程:垃圾回收线程
将线程设置为守护线程的方法:
可以通过调用Thread类的setDaemon(true)方法来设置当前的线程为守护线程。
使用守护线程的注意事项:
1.setDaemon(true)必须在start()方法之前调用,否则会抛出IllegalThreadStateException异常。
2.在守护线程中产生的新线程也是守护线程。
3.不是所有的任务都可以分配给守护线程来执行,比如读写操作或者计算逻辑。原因是:当我们在守护线程中执行着读写操作,当读写操作执行到一半的时候,所有的用户线程都退出来了,那么守护线程就会随JVM虚拟机一起结束工作,然而读写操作还没进行完所以程序就崩溃了。
下面用一个例子解释主线程与守护线程之间的关系:(守护线程在某一个时间内不停的往一个文件中写数据,主线程则阻塞等待键盘的输入,一旦主线程获得了用户的输入阻塞就会解除,主线程继续运行直到结束,而一旦主线程结束守护线程就会销毁,但是守护线程中的写入操作不一定就执行完毕了)

源码:

package com.test.test;import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.Scanner;public class Test {public static void main(String[] args) {System.out.println("进入了主线程"+Thread.currentThread().getName());DaemonThread daemonThread = new DaemonThread();Thread thread  = new Thread(daemonThread);thread.setDaemon(true);//设置为守护线程thread.start();Scanner sc = new Scanner(System.in);sc.next();System.out.println("退出了主线程"+Thread.currentThread().getName());}}class DaemonThread implements Runnable{private String filePath = "C:/Users/Administrator/Desktop/daemon.txt";@Overridepublic void run() {System.out.println("进入了守护线程"+Thread.currentThread().getName());writeToFile();System.out.println("退出了守护线程"+Thread.currentThread().getName());}private void writeToFile() {OutputStream os = null;File filename = new File(filePath);try {os = new FileOutputStream(filename,true);int count = 0;while(count<999){os.write(("\r\nword"+count).getBytes());System.out.println("守护线程"+Thread.currentThread().getName()+"向文件中写入了word"+count++);Thread.sleep(1000);}} catch (Exception e) {e.printStackTrace();}finally{try {os.close();} catch (Exception e) {e.printStackTrace();}}}}

结果截图:

生成的文件内容截图:

通过这个例子:我们可以看到这个程序中只有一个用户线程也就是主线程,当主线程结束的时候,守护线程就会自动销毁(结果就是造成写入的文件不完成)。

通过jstack生成线程快照

jstack的路径位置:
位于jdk/bin目录下
作用:
生成JVM当前时刻线程的快照(threaddump,即当前进程中所有线程 的信息)
目的:
帮助定位程序问题出现的原因,如:长时间停顿,CPU占用率过高等。
使用方法:
在命令提示符中输入jstack,就会显示出jstack的使用帮助。
如图:

这里的-l可有可无,如果有就会打印出线程的一些锁的信息
pid:就是任务管理其中进程的标号
如图:当我启动刚才的程序的时候进程中就会多出一个javaw.exe的进程

图中可以看到PID一项,这里的PID就是我启动的上边的程序进程的标号。
使用jstack运行该程序的PID。如图:

说明:
绿色框中的是进程中其中一个线程的信息。绿框下面的每一段都表示一个现成的信息。
该图中线程状态的说明图:

该图中阻塞状态说明:
Blocked:如果一个线程正在等待一个监视器的锁,那个该线程就处于Blocked状态。eg: 被synchronized阻塞的线程
Waiting:如果一个线程正在无限期的等待另一个线程执行任务,那么这个线程就处于Waiting状态。eg:当线程调用join()方法的时候就会有个线程进入Waiting状态。
Timed_waiting:如果一个线程在指定的时间内等待另一个线程执行任务,那么这个线程就处于Timed_waiting状态。eg:当程序调用了sleep()方法,并在sleep()方法中指定了休眠时间(eg:sleep(1000)形式),那么这个线程就进入了Timed_waiting状态。


所以守护线程处于Timed_waiting状态的原因是,我们在守护线程中调用了sleep(1000)方法。如图:

继续解释命令提示符中的内容

继续查看主线程信息:

Runnable和Thread基础---多线程学习笔记(二)相关推荐

  1. GEE(Google Earth Engine) 最基础代码学习笔记二 —— JavaScript 语言

    GEE(Google Earth Engine) 学习笔记二 Javascript 语言 1. 注释 print('Hello World!'); 如果要注释,则在代码前面加//,比如: // pri ...

  2. 多线程学习笔记二 - 多线程与单例模式

    单例设计模式与多线程: 设计模式:对问题行之有效的解决方式.其实是一种思想. 单例设计模式: 解决的问题:可以保证一个类在内存中的对象唯一性. 比如对于多个程序使用同一个配置信息对象时,都需要保证对象 ...

  3. Python基础函数学习笔记(二)

    一:格式化打印输出: 一个输出时: area = 20.15 print "The area of the circle is %f sq cm."%area 两个输出时: rab ...

  4. Unity基础知识学习笔记二

    1,object Instantiate(object original,Vector3 position,Quaternion rotation)  克隆原始物体,并返回克隆物体. 例如:Insta ...

  5. java 多线程语法_Java基础语法之多线程学习笔记整理

    众所周知,利用好多线程机制,可以大大提高系统整体的并发能力以及性能,而且线程间的切换和调度的成本小.因此,多线程是Java学习者必须掌握的语法重点.本文为大家整理了进程和线程.实现多线程方式.设置和获 ...

  6. linux基础命令学习笔记(二)

    linux基础命令学习笔记(二) 1.kill :终止进程  kill pid (唯一标示一个进程) kill -9  强制终止  kill -15 命令未结束不能终止 # ps aux 查看所有进程 ...

  7. pythonsze_python学习笔记二 数据类型(基础篇)

    Python基础 对于Python,一切事物都是对象,对象基于类创建 不同类型的类可以创造出字符串,数字,列表这样的对象,比如"koka".24.['北京', '上海', '深圳' ...

  8. java多线程学习笔记。

    java多线程学习笔记 线程的优缺点: 多线程的好处: 充分利用多处理核心,提高资源的利用率和吞吐量. 提高接口的响应效率,异步系统工作. 线程的风险: 安全危险(竞争条件):什么坏事都没有发生.在没 ...

  9. 多线程学习笔记20210121

    多线程学习笔记 线程简介 为什么要有线程 用一只手做事情显然是效率比较低的 ,两只手,再来一个人 合作去完成某一件事情显然就会效率高了. 就是在程序执行中 出现了 供需不平衡 了 为了使程序更快,更高 ...

最新文章

  1. ​横扫六大权威榜单后,达摩院开源深度语言模型体系 AliceMind
  2. 一文掌握常用的机器学习模型(文末福利)
  3. 如何避免让微服务测试成为研发团队最大的瓶颈?
  4. HDU 2037 今年暑假不AC【贪心】
  5. pm2集群模式mysql配置_pm2 配置方式
  6. IPC之IPC_PRIVATE与ftok比较
  7. 1.1收集域名信息-完整介绍
  8. 职专计算机怎么学,浅析职业中专计算机专业计算机教学
  9. Spring AOP解析
  10. C++ 中的深入浅拷贝和深拷贝
  11. 在Openstack上创建并访问Kubernetes集群
  12. 京沪等地11月房价半年来首涨 平价走量将成主流
  13. [Alpha阶段]发布说明
  14. 个人财务软件java_个人账务管理系统java
  15. 2022联想创新科技大会--智能为变革赋能
  16. android 触摸接口,Android 多点触摸接口
  17. 2016.11.03回顾 more excel交换两列
  18. USB,蓝牙,以太网,还是WIFI?
  19. 解决戴尔电脑耳机插入后无效,外放正常的问题
  20. 永磁同步电机转子位置估算专题 —— 基波模型类位置估算概要

热门文章

  1. 使用 apifm-wxapi 快速开发小程序
  2. Ajax获取数据的流程
  3. GloVe: Global Vectors for Word Representation-学习笔记
  4. vuepress 代码高亮支持的语言
  5. vue中使用watch监听$route 无效问题
  6. Tomcat配置https访问SSL证书(pfx文件)
  7. ZooKeeper入门(二)Java操作zookeeper
  8. 详细分析图像形态学操作
  9. html5手机端设置date,H5 input[type='date'] 优化 pc端和移动端的使用
  10. AngularJS(6)-选择框Select