java多线程学习
在java中要想实现多线程,有两种手段,一种是继续Thread类,另外一种是实现Runable接口。
一、扩展java.lang.Thread类
package com.multithread.learning;
/**
*@functon 多线程学习
*@author 刁兆建
*@time 2016.10.17
*/
class Thread1 extends Thread{
private String name;
public Thread1(String name) {
this.name=name;
}
public void run() {
for (int i = ; i < ; i++) {
System.out.println(name + "运行 : " + i);
try {
sleep((int) Math.random() * );
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
}
public class Main { public static void main(String[] args) {
Thread1 mTh1=new Thread1("A");
Thread1 mTh2=new Thread1("B");
mTh1.start();
mTh2.start(); } }
输出:
A运行 : 0
B运行 : 0
A运行 : 1
A运行 : 2
A运行 : 3
A运行 : 4
B运行 : 1
B运行 : 2
B运行 : 3
B运行 : 4
再运行一下:
A运行 : 0
B运行 : 0
B运行 : 1
B运行 : 2
B运行 : 3
B运行 : 4
A运行 : 1
A运行 : 2
A运行 : 3
A运行 : 4
注意:
但是start方法重复调用的话,会出现java.lang.IllegalThreadStateException异常。
Thread1 mTh1=new Thread1("A");
Thread1 mTh2=mTh1;
mTh1.start();
mTh2.start();
输出:
Exception in thread "main" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Unknown Source)
at com.multithread.learning.Main.main(Main.java:31)
A运行 : 0
A运行 : 1
A运行 : 2
A运行 : 3
A运行 : 4
二、实现java.lang.Runnable接口
/**
*@functon 多线程学习
*@author 刁兆建
*@time 2016.10.17
*/
package com.multithread.runnable;
class Thread2 implements Runnable{
private String name; public Thread2(String name) {
this.name=name;
} @Override
public void run() {
for (int i = ; i < ; i++) {
System.out.println(name + "运行 : " + i);
try {
Thread.sleep((int) Math.random() * );
} catch (InterruptedException e) {
e.printStackTrace();
}
} } }
public class Main { public static void main(String[] args) {
new Thread(new Thread2("C")).start();
new Thread(new Thread2("D")).start();
} }
输出:
C运行 : 0
D运行 : 0
D运行 : 1
C运行 : 1
D运行 : 2
C运行 : 2
D运行 : 3
C运行 : 3
D运行 : 4
C运行 : 4
三、Thread和Runnable的区别
如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。
package com.multithread.learning;
/**
*@functon 多线程学习,继承Thread,资源不能共享
*@author 刁兆建
*@time 2016.10.17
*/
class Thread1 extends Thread{
private int count=;
private String name;
public Thread1(String name) {
this.name=name;
}
public void run() {
for (int i = ; i < ; i++) {
System.out.println(name + "运行 count= " + count--);
try {
sleep((int) Math.random() * );
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
} public class Main { public static void main(String[] args) {
Thread1 mTh1=new Thread1("A");
Thread1 mTh2=new Thread1("B");
mTh1.start();
mTh2.start(); } }
输出:
B运行 count= 5
A运行 count= 5
B运行 count= 4
B运行 count= 3
B运行 count= 2
B运行 count= 1
A运行 count= 4
A运行 count= 3
A运行 count= 2
A运行 count= 1
从上面可以看出,不同的线程之间count是不同的,这对于卖票系统来说就会有很大的问题,当然,这里可以用同步来作。这里我们用Runnable来做下看看:
/**
*@functon 多线程学习 继承runnable,资源能共享
*@author 刁兆建
*@time 2016.10.17
*/
package com.multithread.runnable;
class Thread2 implements Runnable{
private int count=;
@Override
public void run() {
for (int i = ; i < ; i++) {
System.out.println(Thread.currentThread().getName() + "运行 count= " + count--);
try {
Thread.sleep((int) Math.random() * );
} catch (InterruptedException e) {
e.printStackTrace();
}
} } }
public class Main { public static void main(String[] args) { Thread2 my = new Thread2();
new Thread(my, "C").start();//同一个mt,但是在Thread中就不可以,如果用同一个实例化对象mt,就会出现异常
new Thread(my, "D").start();
new Thread(my, "E").start();
} }
输出:
C运行 count= 15
D运行 count= 14
E运行 count= 13
D运行 count= 12
D运行 count= 10
D运行 count= 9
D运行 count= 8
C运行 count= 11
E运行 count= 12
C运行 count= 7
E运行 count= 6
C运行 count= 5
E运行 count= 4
C运行 count= 3
E运行 count= 2
这里要注意每个线程都是用同一个实例化对象,如果不是同一个,效果就和上面的一样了!
总结:
实现Runnable接口比继承Thread类所具有的优势:
1):适合多个相同的程序代码的线程去处理同一个资源
2):可以避免java中的单继承的限制
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
提醒一下:main方法其实也是一个线程。在java中所以的线程都是同时启动的,至于什么时候,哪个先执行,完全看谁先得到CPU的资源。
在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个jVM实习在就是在操作系统中启动了一个进程。
三、常用函数说明
①sleep(long millis): 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)
②join():指等待t线程终止。
/**
*@functon 多线程学习,join
*@author 林炳文
*@time 2015.3.9
*/
package com.multithread.join;
class Thread1 extends Thread{
private String name;
public Thread1(String name) {
super(name);
this.name=name;
}
public void run() {
System.out.println(Thread.currentThread().getName() + " 线程运行开始!");
for (int i = ; i < ; i++) {
System.out.println("子线程"+name + "运行 : " + i);
try {
sleep((int) Math.random() * );
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " 线程运行结束!");
}
} public class Main { public static void main(String[] args) {
System.out.println(Thread.currentThread().getName()+"主线程运行开始!");
Thread1 mTh1=new Thread1("A");
Thread1 mTh2=new Thread1("B");
mTh1.start();
mTh2.start();
System.out.println(Thread.currentThread().getName()+ "主线程运行结束!"); } }
输出结果:
main主线程运行开始!
main主线程运行结束!
B 线程运行开始!
子线程B运行 : 0
A 线程运行开始!
子线程A运行 : 0
子线程B运行 : 1
子线程A运行 : 1
子线程A运行 : 2
子线程A运行 : 3
子线程A运行 : 4
A 线程运行结束!
子线程B运行 : 2
子线程B运行 : 3
子线程B运行 : 4
B 线程运行结束!
发现主线程比子线程早结束
加join
public class Main {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName()+"主线程运行开始!");
Thread1 mTh1=new Thread1("A");
Thread1 mTh2=new Thread1("B");
mTh1.start();
mTh2.start();
try {
mTh1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
mTh2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+ "主线程运行结束!");
}
}
运行结果:
main主线程运行开始!
A 线程运行开始!
子线程A运行 : 0
B 线程运行开始!
子线程B运行 : 0
子线程A运行 : 1
子线程B运行 : 1
子线程A运行 : 2
子线程B运行 : 2
子线程A运行 : 3
子线程B运行 : 3
子线程A运行 : 4
子线程B运行 : 4
A 线程运行结束!
主线程一定会等子线程都结束了才结束
四、线程同步:
synchronized关键字 synchronized关键字可以作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块。如果再细的分类,synchronized可作用于instance变量、object reference(对象引用)、static函数和class literals(类名称字面常量)身上。
1. 把synchronized当作函数修饰符时,示例代码如下:
Public synchronized void methodAAA()
{
//….
}
public void methodAAA()
{
synchronized (this) // (1)
{
//…..
}
}
java多线程学习的更多相关文章
- Java多线程学习笔记
进程:正在执行中的程序,其实是应用程序在内存中运行的那片空间.(只负责空间分配) 线程:进程中的一个执行单元,负责进程汇总的程序的运行,一个进程当中至少要有一个线程. 多线程:一个进程中时可以有多个线 ...
- Java多线程学习(转载)
Java多线程学习(转载) 时间:2015-03-14 13:53:14 阅读:137413 评论:4 收藏:3 [点我收藏+] 转载 :http://blog ...
- java多线程学习笔记——详细
一.线程类 1.新建状态(New):新创建了一个线程对象. 2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中, ...
- 【转】Java多线程学习
来源:http://www.cnblogs.com/samzeng/p/3546084.html Java多线程学习总结--线程概述及创建线程的方式(1) 在Java开发中,多线程是很常用的,用得好的 ...
- JAVA多线程学习笔记(1)
JAVA多线程学习笔记(1) 由于笔者使用markdown格式书写,后续copy到blog可能存在格式不美观的问题,本文的.mk文件已经上传到个人的github,会进行同步更新.github传送门 一 ...
- Java多线程学习(六)Lock锁的使用
系列文章传送门: Java多线程学习(二)synchronized关键字(1) Java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Java多 ...
- Java多线程学习(五)线程间通信知识点补充
系列文章传送门: Java多线程学习(二)synchronized关键字(1) Java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Java多 ...
- Java多线程学习(四)等待/通知(wait/notify)机制
转载请备注地址:https://blog.csdn.net/qq_34337272/article/details/79690279 系列文章传送门: Java多线程学习(一)Java多线程入门 Ja ...
- Java多线程学习(三)volatile关键字
转载请备注地址:https://blog.csdn.net/qq_34337272/article/details/79680693 系列文章传送门: Java多线程学习(一)Java多线程入门 Ja ...
- Java多线程学习(二)synchronized关键字(2)
转载请备注地址:https://blog.csdn.net/qq_34337272/article/details/79670775 系列文章传送门: Java多线程学习(一)Java多线程入门 Ja ...
随机推荐
- WPS添加页码不是从首页开始
A.页码从第二页开始 "插入"--"页码"--"格式"--不选"续前页"--"起始页码"设为0 &q ...
- springmvc(4)注解简单了解
对于我这样的新人来说,因为是刚开始做项目,所以以前的技术不是用的很多,就比如springmvc来说,实际上使用的都是注解形式的,对于那些全部都是配置的来说,虽然也了解一些,但是实际上还是没试用过的. ...
- 容器--IdentityHashMap
一.概述 IdentityHashMap也是一类特殊的Map,根据其名字,Identity,即同一性,其表现出的具体特点便是,在判断Map中的两个key是否相等时,只通过==来判断,而不通过equal ...
- Javascript——闭包、作用域链
1.闭包:是指有权访问另一个函数作用域中的变量的函数.创建闭包的常见方式:在一个函数内部创建另一个函数. function f(name){ return function(object){ var ...
- 【转】UTF-8汉字正则表达式
原文链接:http://blog.csdn.net/wide288/article/details/30066639 $str = "编程";// if(!preg_match(& ...
- clicaptcha中文点击验证码开发经验总结
现在的验证码真是越来越高级了,12306 的找图验证码,极验的拖动式验证码,还有国外的一些黑科技,能智能判断你是不是机器人的验证码. 验证码的更新迭代让我突然对传统验证码一下子不满足了,出于挑战自我和 ...
- Reapp - 下一代的 Hybrid App 开发框架
Reapp 与 React Native 有着惊人的相似之处,二者都使用 React 来创建应用程序用户界面的框架.然而,在底层机制上这两个框架之间却具有明显的哲学差异.React Native 将 ...
- 我们的动机(Our motivation)
我们的动机(Our motivation) There are many PHP frameworks nowadays, but none of them is like Phalcon (Real ...
- iOS 判断数组是否为空
有人说可以用([array count]==0 )来判断是否为空,都是坑,如果array为空的话,执行count就会直接报错,程序崩溃退出. 正确判断NSArray是否为空的方法:用 (!array) ...
- CRM 2015 快速抓取表单上字段
var table='<table><tr><td>序号</td><td>字段名</td><td>Schema名称& ...