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联 ...
随机推荐
- pyqt5猜数小程序
程序界面用qt设计师制作,并用pyuic5命令转换成form.py文件 #-*- coding:utf-8 -*- from PyQt5.QtWidgets import QApplication,Q ...
- thinkphp 5.0 lnmp环境下 无法访问,报错500(public目录)
两种方法: 1.修改fastcgi的配置文件 /usr/local/nginx/conf/fastcgi.conf fastcgi_param PHP_ADMIN_VALUE "open_b ...
- iOS 11开发教程(一)
iOS 11开发概述 iOS 11是目前苹果公司用于苹果手机和苹果平板电脑的最新的操作系统.该操作系统的测试版于2017年6月6号(北京时间)被发布.本章将主要讲解iOS 11的新特性.以及使用Xco ...
- Visual Studio 2017强制更新方法
Visual Studio 2017强制更新方法 Visual Studio 2017更新时候,用户都是根据消息提示,进行更新.这样做的好处,就是微软可以分批下发升级包,避免集中更新.不过为了早点 ...
- collection 和 collections
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha collection 是集合的意思. 集合 是 集合类的上级接口, 比如 set 和 l ...
- css选择器(第n个类选择器)的坑
css选择器选择第n个子元素,共有两种写法: .parent span:nth-child(n) 选择parent下的第n个子元素(不管前边是不是span,都算在内) .parent span:nth ...
- 为什么Android手机总是越用越慢?
根据第三方的调研数据显示,有77%的Android手机用户承认自己曾遭遇过手机变慢的影响,百度搜索“Android+卡慢”,也有超过460万条结果.在业内,Android手机一直有着“越用越慢”的口碑 ...
- centos7安装kafka_2.11-1.0.0 新手入门
系统环境 1.操作系统:64位CentOS Linux release 7.2.1511 (Core) 2.jdk版本:1.8.0_121 3.zookeeper版本:zookeeper-3.4.9. ...
- Linux rescue
适用场景: 当误操作修改系统启动文件/etc/fstab, /etc/rc.d/rc.sysinit时,就会造成系统启动时读取磁盘或初始化环境失败,导致linux无法正常启动,此时就可以借助Linux ...
- Git_操作标签
如果标签打错了,也可以删除: $ git tag -d v0.1 Deleted tag 'v0.1' (was e078af9) 因为创建的标签都只存储在本地,不会自动推送到远程.所以,打错的标签可 ...