Java的多线程机制
1.利用Thread的子类创建线程
例1.用Thread子类创建多线程程序。
先定义一个Thread的子类,该类的run方法只用来输出一些信息。
package thread; public class myThread extends Thread{
private static int count=0; public void run() {
int i;
for(i=0;i<100;i++){
count=count+1;
System.out.println("My name is "+getName()+" count="+count);
try {
sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public myThread(String name){
super(name);
} }
下面用程序来创建线程对象并运行该线程对象。
package thread; public class mulThread { public static void main(String[] args) {
myThread trFirst,trSecond;
trFirst = new myThread("First Thread");
trSecond = new myThread("Second Thread");
trFirst.start();
trSecond.start();
System.out.println("主线程结束!");
} }
2.实现Runnable接口创建线程
例2. 继承Runnable接口实现多线程。
package thread; public class ThreadImRunable implements Runnable{
private static int count=0;
private Thread t;
public void run() {
int i;
for(i=0;i<100;i++){
count++;
System.out.println("My name is "+t.getName()+" count="+count);
try {
t.sleep(10);
} catch (Exception e) {
// TODO: handle exception
}
}
} public ThreadImRunable(String name){
t = new Thread(this,name);
} public void start(){
t.start();
}
}
主程序跟前面相同。
package thread; public class mulThread { public static void main(String[] args) {
myThread trFirst,trSecond;
trFirst = new myThread("First Thread");
trSecond = new myThread("Second Thread");
trFirst.start();
trSecond.start();
System.out.println("主线程结束!");
} }
3.使用isAlive()和join()等待子线程结束
例3. join()方法使用示例。
package thread; public class demoJoin {
public static void main(String[] args){
myThread trFirst,trSecond;
trFirst = new myThread("First Thread");
trSecond = new myThread("Second Thread");
try {
trFirst.start();
trSecond.start();
trFirst.join();
trSecond.join();
} catch (InterruptedException e) {
System.out.println("主线程被中断!");
}
System.out.println("主线程结束!");
}
}
4.设置线程优先级
例4. 设置线程优先级示例。
package thread; public class clicker extends Thread{
private int click=0;
private volatile boolean running=true;//volatile告诉编译器,不要自作主张为它编译优化
public int getClick(){
return click;
} public void run() {
while(running){
click = click + 1;
}
} public void normalStop(){
running = false;
} }
程序中的循环变量running被声明成volatile,这个关键字告诉编译器,不要自作主张为它进行编译优化。
注意:不要将循环体中“click=click+1”改成“++click”的形式。对于前者,编译器会生成多条命令,执行过程中系统有机会将它中断。而后者只有一条指令,系统不能将其中断,这样其他进程就难以有机会使用CPU。
package thread; public class demoPri { public static void main(String[] args) {
clicker c1High,c2Low;
c1High=new clicker();
c2Low=new clicker();
c1High.setPriority(Thread.NORM_PRIORITY+2);
c2Low.setPriority(Thread.NORM_PRIORITY-2);
c2Low.start();
c1High.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} c1High.normalStop();
c2Low.normalStop(); try {
c1High.join();
c2Low.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("c1High执行循环的次数为:"+c1High.getClick());
System.out.println("c2Low 执行循环的次数为:"+c2Low.getClick());
} }
程序的输出结果为:
c1High执行循环的次数为:427835536
c2Low 执行循环的次数为:396647205
结果表明,优先级高的线程获得了更多的CPU运行时间。
5.线程的互斥
例5. 线程互斥示例。
package thread; public class mutixThread extends Thread{
private static int count = 0;
private synchronized static void change(Thread t){
count = count + 1;
System.out.println("My name is "+t.getName()+" count="+count);
} public void run() {
int i;
for(i=0;i<100;i++){
change(this);
try {
sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} public mutixThread(String name){
super(name);
}
}
下面写一个程序测试它的运行情况。
package thread; public class demoMutix {
public static void main(String[] args){
mutixThread t1,t2,t3;
t1 = new mutixThread("First Thread");
t2 = new mutixThread("Second Thread");
t3 = new mutixThread("Third Thread");
t1.start();
t2.start();
t3.start();
try {
t1.join();
t2.join();
t3.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} System.out.println("主线程结束");
}
}
程序运行结果如下:
.....
My name is Third Thread count=297
My name is First Thread count=298
My name is Third Thread count=299
My name is Second Thread count=300
主线程结束
6.线程的同步
例6. 线程同步示例。
package thread; public class commSource {
static boolean flag = true;
static int data;
static int count;
}
package thread; public class setDataThread extends Thread {
private readDataThread otherThread=null; //存储另外一个线程对象
public void run(){
for(int i=0;i<100;i++){
if(!commSource.flag)
try {
synchronized(this){ //锁定当前对象
wait(); //阻塞自己
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
commSource.flag = false;
commSource.data = (int)(Math.random()*1000);
commSource.count++;
System.out.println("设置数据:"+commSource.data+" count="+commSource.count);
synchronized(otherThread){ //锁定另外一个线程对象
otherThread.notify(); //唤醒另外一个线程对象
}
}
}
public void setOtherThread(readDataThread rt){
otherThread=rt;
}
}
package thread; public class readDataThread extends Thread{
private setDataThread otherThread = null;
public void run(){
for(int i=0;i<100;i++){
if(commSource.flag)
try {
synchronized(this){
wait();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
commSource.flag = true;
System.out.println("获得数据:"+commSource.data);
synchronized(otherThread){
otherThread.notify();
}
}
}
public void setOtherThread(setDataThread st){
otherThread = st;
}
}
package thread; public class demoSynchorny { public static void main(String[] args) {
setDataThread str;
readDataThread rtr;
str=new setDataThread();
rtr=new readDataThread();
str.setOtherThread(rtr);
rtr.setOtherThread(str);
str.start();
rtr.start(); } }
输出结果如下:
设置数据:295 count=1
获得数据:295
......
设置数据:974 count=99
获得数据:974
设置数据:526 count=100
获得数据:526
两个线程是严格交替运行的。
7.暂停恢复和停止线程
例7. 自己编写线程的暂停、恢复和停止方法。
package thread; public class enhanceThread extends Thread {
private static final int STOP = 1;
private static final int RUNNING = 2;
private static final int SUSPEND = 3;
private int state = STOP;
public synchronized void run(){
int cnt = 0;
while(state!=STOP){
if(state==SUSPEND){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
++cnt;
System.out.println("线程正在运行:"+cnt);
try {
sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} public void normalStop(){
state = STOP;
} public void normalSuspend(){
state = SUSPEND;
} //恢复线程运行
public synchronized void normalResume(){
state = RUNNING;
notify();
} public enhanceThread(){
state = RUNNING;
}
}
package thread; public class demoEhanceThread { public static void main(String[] args) {
enhanceThread tr;
tr = new enhanceThread();
System.out.println("启动线程!");
tr.start();
try {
Thread.sleep(1000);
System.out.println("将线程挂起!");
tr.normalSuspend();
Thread.sleep(1000);
System.out.println("恢复线程运行!");
tr.normalResume();
Thread.sleep(1000);
System.out.println("终止线程运行!");
tr.normalStop();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } }
输出结果如下:
启动线程!
线程正在运行:1
线程正在运行:2
线程正在运行:3
线程正在运行:4
线程正在运行:5
线程正在运行:6
线程正在运行:7
线程正在运行:8
线程正在运行:9
线程正在运行:10
将线程挂起!
恢复线程运行!
线程正在运行:11
线程正在运行:12
线程正在运行:13
线程正在运行:14
线程正在运行:15
线程正在运行:16
线程正在运行:17
线程正在运行:18
线程正在运行:19
线程正在运行:20
终止线程运行!
8.生产者-消费者问题实例
例8. 生产者-消费者实例。
package thread; public class common {
private int production[]; //存放产品的缓冲区
private int count; //产品的实际数目
private int BUFFERSIZE = 6; //缓冲区大小
public common(){
production = new int[BUFFERSIZE];
count = 0;
}
//从缓冲区中取数据
public synchronized int get(){
int result;
while(count<=0)
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
result = production[--count];
notifyAll();
return result;
}
//向缓冲区中写数据
public synchronized void put(int newproduct){
while(count>=BUFFERSIZE)
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
production[count++]=newproduct;
notifyAll();
}
}
package thread;
//消费者线程
public class consumer extends Thread {
private common comm;
public consumer(common mycomm){
comm = mycomm;
} public synchronized void run(){ //线程体
int i,production;
for(i=1;i<=20;i++){ //消费线程计数
production = comm.get();
System.out.println("得到的数据为:"+production);
try {
sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
package thread;
//生产者线程
public class producer extends Thread {
private common comm;
public producer(common mycomm){
comm = mycomm;
} public synchronized void run(){
int i;
for(i=1;i<=10;i++){
comm.put(i);
System.out.println("生产的数据为:"+i);
try {
sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
package thread; public class producer_consumer {
public static void main(String[] args){
common comm = new common();
producer p1 = new producer(comm);
producer p2 = new producer(comm);
consumer c1 = new consumer(comm);
p1.start();
p2.start();
c1.start();
}
}
程序某次运行结果如下:
生产的数据为:1
得到的数据为:1
生产的数据为:1
得到的数据为:2
生产的数据为:2
生产的数据为:2
生产的数据为:3
得到的数据为:3
生产的数据为:3
生产的数据为:4
得到的数据为:4
生产的数据为:4
生产的数据为:5
得到的数据为:5
生产的数据为:5
得到的数据为:5
生产的数据为:6
生产的数据为:6
得到的数据为:6
生产的数据为:7
生产的数据为:8
得到的数据为:7
得到的数据为:8
生产的数据为:9
生产的数据为:10
得到的数据为:9
得到的数据为:10
生产的数据为:7
得到的数据为:7
生产的数据为:8
得到的数据为:8
生产的数据为:9
得到的数据为:9
生产的数据为:10
得到的数据为:10
得到的数据为:6
得到的数据为:4
得到的数据为:3
得到的数据为:2
得到的数据为:1
结果表明,该程序已经很好地解决了生产者线程和消费者线程间的同步问题。
Java的多线程机制的更多相关文章
- Java的多线程机制系列:不得不提的volatile及指令重排序(happen-before)
一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...
- Java的多线程机制系列:(四)不得不提的volatile及指令重排序(happen-before)
一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...
- Java的多线程机制系列:(三)synchronized的同步原理
synchronized关键字是JDK5之实现锁(包括互斥性和可见性)的唯一途径(volatile关键字能保证可见性,但不能保证互斥性,详细参见后文关于vloatile的详述章节),其在字节码上编译为 ...
- 沉淀再出发:再谈java的多线程机制
沉淀再出发:再谈java的多线程机制 一.前言 自从我们学习了操作系统之后,对于其中的线程和进程就有了非常深刻的理解,但是,我们可能在C,C++语言之中尝试过这些机制,并且做过相应的实验,但是对于ja ...
- Java的多线程机制系列:(一)总述及基础概念
前言 这一系列多线程的文章,一方面是个人对Java现有的多线程机制的学习和记录,另一方面是希望能给不熟悉Java多线程机制.或有一定基础但理解还不够深的读者一个比较全面的介绍,旨在使读者对Java的多 ...
- Java的多线程机制系列:(二)缓存一致性和CAS
一.总线锁定和缓存一致性 这是两个操作系统层面的概念.随着多核时代的到来,并发操作已经成了很正常的现象,操作系统必须要有一些机制和原语,以保证某些基本操作的原子性.首先处理器需要保证读一个字节或写一个 ...
- Java中多线程原理详解
Java是少数的集中支持多线程的语言之一,大多数的语言智能运行单独的一个程序块,无法同时运行不同的多个程序块,Java的多线程机制弥补了这个缺憾,它可以让不同的程序块一起运行,这样可以让程序运行更加顺 ...
- Java—事件和多线程机制
一 事件 1.1 事件源 图形用户界面上每个可能产生事件的组件称为事件源. 1.2 事件监听者 Java系统中注册的用于接收特殊事件的类.不同的事件对应着不同的监听者,要想事件被监听者监听并处理,则 ...
- 【转载】Java垃圾回收机制
原文地址:http://www.importnew.com/19085.html Java垃圾回收机制 说到垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它和Java联 ...
随机推荐
- PHP 统计数据合并
将不同的统计结果整合在一起,如图,根据年级统计出不同成绩段人数(此处只为举例),然后写了一个方法来处理这些统计数组 <?php /** * 合并统计数据 * @param $key_column ...
- 为mongodb数据库增加用户名密码权限
加固mongodb建议:修改数据库默认端口,添加数据库访问权限: 启动数据库(裸奔):C:\mongodb\bin>mongod --dbpath C:\MongoDB\data(同时用--db ...
- “公共语言规范”(CLS)
一.什么是“公共语言规范”(CLS) 定义了一个最小公共集,任何编译器只有支持这个功能集,生成的类型才能兼容其他符合CLS.面向CLR的语言生成的组件 二.CLS规则 类型的每个成员要么是字段(数据) ...
- [ 原创 ] Java基础1--Java中super和this的用法和区别
许多同学在学习Java时分不清楚this和super的用法和区别,今天偶然发现一片加精的博文,看完内容准备自己也写下来积累一下 1.如果想在子类的构造方法中调用父类的构造方法,必须在子类的构造方法中使 ...
- java设计模式(六)策略模式
适用于同一操作的不同行为,策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们可以相互替换,让算法独立于使用它的客户而独立变化,具体应用场景如第三方支付对接不同银行的算法. 要点:1)抽象策 ...
- lor框架代码分析
属性 lor: version router route request response fn app create_app Router Route Request Response 属性 lor ...
- ASP.NET 构建高性能网站 第4篇
部署优化 我们都知道,不同的部署方式对站点的性能是有影响的,可能有些朋友已经知道了这点,不管怎样,我们这里还是详细系统的讲述一下这个问题,熟悉的朋友权当回顾J. Release方式编译项目 如果我们的 ...
- centos7安装apache 新手入门 图文教程
操作系统 64位CentOS Linux release 7.2.1511 (Core) 下载apache相关软件 1.apr和apr-util,下载地址: http://apr.apache.org ...
- IntelliJ IDEA 查看继承关系
在 IntelliJ IDEA 中这个查看一个类也就是当前类的所有继承关系,包括实现的所有的接口和继承的类, 这个继承,不仅仅是一级的继承关系,包括好几层的继承.父类的父类的父类.直到最后.可以很清楚 ...
- Go语言Web框架gwk介绍 (五)
Session Go的net/http本身不带session的机制,需要开发人员自行实现,gwk实现了内存中的session存储机制,如果需要将session存在其他地方比如redis或者memcac ...