Java中的多线程开发

在实际的应用中,经常一种需要持续的工作,比如我们做过的网络程序中,在客户端需要持续的读取服务器发送过来的消息,在服务器端需要持续的读取客户端发送过来的消息。这种持续性的工作,通常在一个while循环中执行,只有当循环条件不满足的时候,才终止while循环。比如下面的例子:

package thread;

public class NormalObject {

	public long runtimes;
	public boolean stop;
	public NormalObject(){
		stop=false;
		runtimes=0;
	}
	public void run(){
		int run=0;		
		while(!stop){
			run ++;
			if(run>10000){
				runtimes ++;
				run =0;
			}				
		}
	}
}

这是一个普通的对象,当创建对象之后,调用对象的run方法,对象就持续的运行,直到stop这个值变成false的时候,它才停止。就像下面的:


NormalObject normalObject = new NormalObject();
	normalObject.stop = false;
	normalObject.run();

normalObject对象会一直运行,直到我们把它的stop字段设置为false为止。

 

但是while循环是非常消耗CPU时间的,一旦运行起来,就会占用大部分的CPU时间,其余的操作几乎没法进行了。比如我们设计如下的一个程序:

 

创建一个窗口程序,上面有个按钮,显示的是“Start”,当点击它之后,就运行normalObject,同时把“Start”改成“End”,然后再点击一次,就会让normalObject停止,同时把“End”改成“Start”。

我们写出如下的代码:


package ui;

import java.awt.EventQueue;

public class MainFram {

	private JFrame frame;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					MainFram window = new MainFram();
					window.frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public MainFram() {
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frame = new JFrame();
		frame.setBounds(100, 100, 450, 300);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		final NormalObject normalObject = new NormalObject();
		final JButton btnNewButton = new JButton("Start");
		btnNewButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
//点击按钮,执行逻辑
				if (btnNewButton.getText().equals("Start")) {
					btnNewButton.setText("End");
					normalObject.stop = false;
					normalObject.run();
				} else {
					btnNewButton.setText("Start");
					normalObject.stop = false;
				}
			}
		});
		frame.getContentPane().add(btnNewButton, BorderLayout.SOUTH);
	}

}


测试运行,可以看到,没法达到我们的目的。

 

分析一下可以看出,normalObject.run()方法是一直在执行while,所以退不出来,其他的代码也得不到执行,系统出现了“卡死”现象。

 

这是因为,当我们点击程序开始运行的时候,系统就会创建一个线程,这个线程在执行main方法中的代码,我们的窗体就是在main方法中创建的,所以窗体运行在这个线程上面。当这个线程运行到normalObject.run()的时候,就进入while循环了,别的代码就执行不了了。

 

对这个问题的解决方法,就是创建另外的一个线程,让那个累加操作(normalObject.run())运行在其他的线程中,它会和main所在的线程并发执行,就不再干扰到窗体中其他的响应了。我们对normalObject修改如下:


package thread;

public class ThreadObject extends Thread {

	public long runtimes;
	public boolean stop;
	public ThreadObject(){
		stop=false;
		runtimes=0;
	}
	public void run(){
		int run=0;		
		while(!stop){
			run ++;
			if(run>10000){
				runtimes ++;
				run =0;
			}				
		}
	}

}


注意:类的名字换了,所以需要新建一个类。

 

 

再修改窗体代码如下:

package ui;

import java.awt.EventQueue;

public class MainFram {

	private JFrame frame;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					MainFram window = new MainFram();
					window.frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public MainFram() {
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frame = new JFrame();
		frame.setBounds(100, 100, 450, 300);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		final ThreadObject normalObject = new ThreadObject();
		final JButton btnNewButton = new JButton("Start");
		btnNewButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if (btnNewButton.getText().equals("Start")) {
					btnNewButton.setText("End");					
					normalObject.stop = false;
					normalObject.start();
				} else {
					btnNewButton.setText("Start");
					normalObject.stop = false;
				}
			}
		});
		frame.getContentPane().add(btnNewButton, BorderLayout.SOUTH);
	}

}



注意修改的代码我用红色下划线标志出来了,同上面的区别可以比较。

 

然后在运行,就可以看到达到我们的要求了。

 

这就是因为,在新的代码中,当执行到normalObject.start()的时候,系统会开辟一个新的同main所在线程并列的线程,然后normalObject中run()方法中的代码就跑到新的线程中去运行了,从而使得main所在线程继续能执行下面的代码了。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值