细说Java多线程
来源:互联网 发布:平安信用卡网络支付 编辑:程序博客网 时间:2024/06/05 08:41
Java中有关线程的类有两个:Thread和Runnble
下面是创建线程的两种方式:
1:继承Thread类
class myThread extends Thread{
...
@Overread
public void run(){
...
}
}
myThread mt=new myThread(); //创建线程
mt.run();//启动线程
2:实现Runnable接口
class myThread implements Runnable{
@Override
public void run() {
}
}
myThread mt=new myThread();
Thread td=new Thread(mt);
td.start();
Runnable方式可以避免Thread方式由于Java单继承特性带来的缺陷;
Runnable的代码可以被多个线程(Thread实例)共享,适用于多个线程处理同一资源;
通过下面的实例来分析两种方式的区别:
模拟火车站卖票的场景,假设有3个窗口卖火车票,火车票总数一共有5张;
1:继承Thread类的方式;
class MyThread extends Thread{
private int ticketscount=5;//一共5张火车票
private String name;//窗口,也即是线程的名字
public MyThread(String name) {
this.name = name;
}
@Override
public void run() {
while(ticketscount>0){
ticketscount--;
System.out.println(name+"卖了一张票,剩余票数"+ticketscount);
}
}
}
public class TicketsThread {
public static void main(String[] args) {
//创建三个线程,模拟三个窗口卖票;
MyThread mt1=new MyThread("窗口1");
MyThread mt2=new MyThread("窗口2");
MyThread mt3=new MyThread("窗口3");
mt1.start();
mt2.start();
mt3.start();
}
}
程序的运行结果如下:
窗口3卖了一张票,剩余票数4
窗口1卖了一张票,剩余票数4
窗口1卖了一张票,剩余票数3
窗口1卖了一张票,剩余票数2
窗口1卖了一张票,剩余票数1
窗口1卖了一张票,剩余票数0
窗口2卖了一张票,剩余票数4
窗口3卖了一张票,剩余票数3
窗口2卖了一张票,剩余票数3
窗口3卖了一张票,剩余票数2
窗口2卖了一张票,剩余票数2
窗口3卖了一张票,剩余票数1
窗口2卖了一张票,剩余票数1
窗口3卖了一张票,剩余票数0
窗口2卖了一张票,剩余票数0
可以看到,每个线程中都卖了5张票,加起来一共是15张票.
2:实现Runnable接口的方式
class MyThread implements Runnable{
private int ticketscount=5;//一共5张火车票
@Override
public void run() {
while(ticketscount>0){
ticketscount--;//如果还有票,就卖掉一张;
System.out.println(Thread.currentThread().getName()+"卖了一张票,剩余票数"+ticketscount);//当前线程的名字;
}
}
}
public class TicketsRunnable {
public static void main(String[] args) {
MyThread mt=new MyThread();
Thread th1=new Thread(mt,"窗口1");
Thread th2=new Thread(mt,"窗口2");
Thread th3=new Thread(mt,"窗口3");
th1.start();
th2.start();
th3.start();
}
}
程序运行结果:
窗口1卖了一张票,剩余票数4
窗口3卖了一张票,剩余票数3
窗口2卖了一张票,剩余票数2
窗口3卖了一张票,剩余票数0
窗口1卖了一张票,剩余票数1
可以看出三个线程一共卖了5张票;
方式二的代码稍作更改之后:
class MyThread implements Runnable{
private int ticketscount=5;//一共5张火车票
@Override
public void run() {
while(ticketscount>0){
ticketscount--;//如果还有票,就卖掉一张;
System.out.println(Thread.currentThread().getName()+"卖了一张票,剩余票数"+ticketscount);//当前线程的名字;
}
}
}
public class TicketsRunnable {
public static void main(String[] args) {
MyThread mt1=new MyThread();
MyThread mt2=new MyThread();
MyThread mt3=new MyThread();
Thread th1=new Thread(mt1,"窗口1");
Thread th2=new Thread(mt2,"窗口2");
Thread th3=new Thread(mt3,"窗口3");
th1.start();
th2.start();
th3.start();
}
}
运行结果:
窗口3卖了一张票,剩余票数4
窗口2卖了一张票,剩余票数4
窗口1卖了一张票,剩余票数4
窗口2卖了一张票,剩余票数3
窗口3卖了一张票,剩余票数3
窗口2卖了一张票,剩余票数2
窗口1卖了一张票,剩余票数3
窗口2卖了一张票,剩余票数1
窗口2卖了一张票,剩余票数0
窗口3卖了一张票,剩余票数2
窗口3卖了一张票,剩余票数1
窗口3卖了一张票,剩余票数0
窗口1卖了一张票,剩余票数2
窗口1卖了一张票,剩余票数1
窗口1卖了一张票,剩余票数0
这个时候每个线程都有了5 张票;
线程的生命周期:
Java线程有两类:
1:用户线程;
运行在前台,执行具体的任务。程序的主线程,连接网络的子线程等都是用户线程;
2 : 守护线程;
运行在后台,为其它前台线程服务;
特点:一旦所有用户线程都结束运行,守护线程会随JVM一起结束工作;
应用:数据库连接池中的监测线程;
JVM虚拟机启动后的监测线程;
最常见的守护线程:垃圾回收线程;
如何设置守护线程:可以通过调用Thread类的setDaemon(true)方法来设置当前的线程为守护线程;
注意事项:setDaemon(true)必须在start()方法执行前调用;
在守护线程中产生的线程也是守护线程;
不是所有的任务都可以分配给守护线程来执行,比如读写操作与计算逻辑;
使用jstack生成线程快照:
jatack的作用:生成当前时刻线程的快照,(threaddump,即当前进程中所有线程的信息);
目的:帮助定位程序问题出现的原因,如长时间停顿,cpu占用率过高等;
使用方法:打开命令行,键入 jstack可以看到提示使用方式,键入jstack -l pid 可以查看线程id为pid的快照,如下图:
daemon代表是守护线程,java.lang.Thread.State代表着该线程的状态;
- 细说Java多线程
- 细说Java多线程之内存可见性
- Java 细说多线程之内存可见性
- 慕课网--细说java 多线程 thread与runnable的区别
- 一系列1: 细说Java多线程之内存可见性
- 细说Java
- C# 细说多线程
- 细说C#多线程(上)
- 细说C#多线程(下)
- C# 细说多线程(上)
- C# 细说多线程(下)
- 细说多线程1
- 细说多线程2
- 细说qt多线程(一)
- c#—细说多线程(1)
- 细说C#多线程那些事
- 细说JAVA反射
- 细说Java引用类型
- C语言内存管理
- js验证
- MapReduce job运行的几种模式
- SVM多分类
- ZYNQ中断配置函数
- 细说Java多线程
- StringBuffer类的使用
- red+flex实现视频通信
- eclipse中tomcat能正常启动,但是浏览器访问不了tomcat首页 问题解决
- 剑指offer(C++)——字符流中第一个不重复的字符
- java字符逆序
- 开篇
- Bagging and Boosting 概念和区别
- astgo 老版本免激活完整安装包带安装命令脚本