栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java线程系列(四)多线程的优势和风险(线程安全问题)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java线程系列(四)多线程的优势和风险(线程安全问题)

多线程的优势

多线程可以让一个进程有多个并发操作,及多个任务在同一个时间被执行,提高了系统的吞吐率,而且一个进程中的多个线程可以共享其所在进程所申请的资源,如内存空间,节约了对系统资源的利用率。
下面用一个彩色线条的例子来体现多线程:

UI.java

import java.awt.Graphics;

import javax.swing.Jframe;

public class UI {

	public static void main(String[] args) {
		UI myui=new UI();
		myui.Initl();
	}
	
	void Initl() {
		//初始化界面
		Jframe myjf=new Jframe();
		myjf.setTitle("多线程示例");
		myjf.setSize(800,600);
		myjf.setDefaultCloseOperation(3);
		myjf.setLocationRelativeTo(null);
		myjf.setVisible(true);
		
		Graphics g=myjf.getGraphics();
		
		//创建监听器对象,并给窗体加上鼠标监听器
		Mouse_Lis listener=new Mouse_Lis();
		myjf.addMouseListener(listener);
		
		//创建线程类对象,把鼠标点击后获取的矩形对象传给线程类
		Thread_Rec rectangle=new Thread_Rec(g);
		rectangle.reclist=listener.reclist;
		
		//创建线程并启动
		Thread thr1=new Thread(rectangle);
		thr1.start();
	}
}

Rectangle.java

import java.awt.Color;
import java.awt.Graphics;

public class Rectangle {

	
	int x,y,speedx,speedy,size;
	Color color;
	//构造方法
	public Rectangle(int x,int y,int speedx,int speedy,int size,Color color) {
		// TODO Auto-generated constructor stub
		this.x=x;
		this.y=y;
		this.speedx=speedx;
		this.speedy=speedy;
		this.size=size;
		this.color=color;
	}
	
	//小矩形绘制
	void Draw(Graphics g) {
		g.setColor(color);
		g.fillRect(x, y, size, size);
	}
	
	//小矩形移动
	void Move() {
		if(x<0||x>1000) {
			speedx=-speedx;
		}else if(y<0||y>800) {
			speedy=-speedy;
		}
		x+=speedx;
		y+=speedy;
	}
}

Mouse_Lis.java

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Random;

public class Mouse_Lis extends MouseAdapter{

	
	ArrayList reclist=new ArrayList();
	
	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO Auto-generated method stub
		int x=e.getX();
		int y=e.getY();
		Random ran=new Random();
		Color color=new Color(ran.nextInt(Integer.MAX_VALUE));
		
		Rectangle rectan=new Rectangle(x,y,1,1,30,color);
		reclist.add(rectan);//入队列
	}	

}

Thread_Rec.java

import java.awt.Graphics;
import java.util.ArrayList;

public class Thread_Rec implements Runnable{

	ArrayList reclist;
	Graphics g;
	public Thread_Rec(Graphics g) {
		this.g=g;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(true) {
			for(int i=0;i 

这是一个线程,可如果我们,在界面类做如下改进,启动多个线程的话:

		Thread thr2=new Thread(rectangle);
		thr2.start();
		Thread thr3=new Thread(rectangle);
		thr3.start();

绘制速度会明显加快。
单线程就好比你踢了一次球,而多线程相当于你多次踢了同一个球,很明显该球会变得更快。当然这并不是线性的叠加,讲线程问题时会提到。

线程问题的发现

运行单线程时效果如下:

运行多线程时效果如下:

仔细观察就会发现单线程虽然速度慢,但它的线条笔直,而且颜色非常纯正,而多线程虽然速度快,但是会有颜色突变,为什么呢?

线程问题的解释

多个线程在共享数据时,很可能产生数据一致性的问题,如读取过期的数据,某些线程所做的更新被其他线程所做的更新更改等。例如上述例子:因为多个线程共有一个画笔g,在一个线程还未绘制完矩形时画笔的颜色已被另一个线程所更改。

线程问题的解决

这种情况在真正的大型系统中是十分危险的。在介绍解决办法之前先了解几个名词:
原子操作
原子操作是指单一不可分割的操作。例如:int x=2;虽然是一条语句,但是实际操作时却分为两步:(1)声明变量x;(2)给变量赋值为2。第一步和第二步之间是可以被其他线程打断的,故不是原子操作。
锁:如果不想某段代码在运行时被打断,可以通过对该段代码上锁来把它变成 “原子操作” 。
解决:使用关键字synchronized给代码上锁来实现操作的原子性,其本质是通过该关键字所包含的临界区(Critical Section)的排他性保证在任何一个时刻只有一个线程能执行临界区的代码。

举例说明 代码改进

在线程类的run方法中给代码加锁:

public void run() {
		// TODO Auto-generated method stub
		while(true) {
			for(int i=0;i 

程序运行效果如下:

速度依旧很快,也没有颜色突变的情况了。

再举例 (计数器)

E.java

public class E implements Runnable{
	int count=0;
	public static void main(String[] agrs) {
		E e=new E();
		Thread th=new Thread(e);
		th.start();
		Thread th2=new Thread(e);
		th2.start();
		Thread th3=new Thread(e);
		th3.start();
	}

	@Override
	public void run() {
		while(true) {
			for(int i=0;i<100;i++) {
				count++;
				try {
					Thread.sleep (15); 
					} catch (InterruptedException e) {
						e.printStackTrace (); 
						}
			}
			System.out.println("count="+count);
		}
			
	}
}

程序运行时按理来说count应该是成百成百地增加,但实际情况却是:

给循环加锁之后:

总结

多线程虽好,可要注意安全问题噢~

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/602907.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号