新手求救《线程问题》 关于线程是怎么一回事 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 Swing线程说明Swing的原则:只有从事件派发线程才能更新Swing组件Swing中的线程有三种:初始线程、事件线程、工作线程初始线程:用来创建GUI组件、资源加载和启动GUI组件,当UI出现之后,初始线程就完成了使命。事件线程:即Swing线程、事件分派线程、AWT线程、Event Dispatch Thread。Swing所有组件的事件行为都交给这个线程进行处理,Swing线程是和Swing组件进行交互的唯一的线程,所有的绘制和图形、鼠标事件、组件事件、按钮事件和所有其他事件都发生在Swing线程。工作线程:这是我们自己需要运行其他任务的线程,优秀的GUI程序绝不能让界面卡死,会让用户崩溃,所以这时候需要工作线程,也可以说是在背后运行的线程。使用多线程的优势:1, 当有大量数据操作时,不让界面卡死;2, 多线程可以提高性能,多个线程同时操作,能充分利用资源线程尽量要少用,原因如下:1, 一个进程中的多个线程共享相同的内存地址控件,这就以为着他们可以访问相同的变量和对象,而且他们从同一个堆中分配对象,这里可能会造成线程的互相干扰。2, 过度使用线程可能会危及程序的性能及其可维护性。与线程相关的API:Thread、Runnable、SwingUitilitiesThread:java提供的一个抽象类,该类里面有个一个抽象的run()方法,我们在写程序时,只要继承于这个类,实现run()方法就可以了,在程序中,如果我们想用另一个线程来执行一些动作,这要把这些动作的代码写在run()方法中,然后再调用从Thread类继承来的start()方法。如:public class MyThread extends Thread{ static MyThread mt=new MyThread(); public static void main(String args[]){ mt.start(); for(int i=0;i<100;i++){ System.out.println("i=" +i); } } public void run(){ for(int j=0;j<100;j++){ System.out.println("j= "+j); } }} Thread的其他方法:sleep()、stop()Runnable: Java提供了两种机制实现多线程,可以继承Thread类,也可以通过Runnable接口实现。public class RunnableDemo implements Runnable{ Thread thread2=new Thread(this,"2"); public void run() { // TODO Auto-generated method stub System.out.println("线程:"+thread2.getName()+"开始运行!"); for(char ch='A';ch<='Z';ch++){ System.out.println(ch); try{ thread2.sleep(10); }catch(InterruptedException e){ System.out.println("线程2异常"); } } } public static void main(String[] args){ Thread thread2=new Thread(new RunnableDemo()); thread2.start(); for(int i=0;i<100;i++){ System.out.println("i=" +i); } }}SwingUitilities:提供了两个方法invokeLater和invoteAndWait,他们都是使事件派发线程上的可运行对象排队。当可运行对象排在事件派发队列的队首时,就调用其run方法。其效果是允许事件派发线程调用另一个线程中的任意一个代码块。invokeandwait()方法阻塞直到runnnable执行完毕;invokelater()异步地执行runnable。invokeandwait()一般不赞成使用,因为它可能导致严重的线程死锁,对你的应用造成严重的破坏。所以,让我们把它放置一边,使用invokelater()方法。实例:看下面这段代码的演变过程:目的是实现一个按钮的事件;文本框(searchTF)、按钮(searchButton)、输出文本区(outputTA);lookup是一个费时查询过程; 第一版本: private void searchButton_actionPerformed(){ outputTA.setText("Searching for: "+searchTF.getText()); String[] results=lookup(searchTF.getText()); outputTA.setText(""); for (int i = 0; i < results.length; i++) { String result = results[i]; outputTA.setText(outputTA.getText() + '\n' + result); } }问题:由于lookup比较费时,界面看上去像卡死了解决办法:lookup这个非swing任务起一个工作线程,如下代码 private void searchButton_actionPerformed(){ outputTA.setText("Searching for: "+searchTF.getText()); final String[][] results=new String[1][1]; new Thread(){ public void run(){ results[0]=lookup(searchTF.getText()); } }.start(); outputTA.setText(""); for (int i = 0; i < results[0].length; i++) { String result = results[0][i]; outputTA.setText(outputTA.getText() + '\n' + result); } }问题:后面的结果显示将不会等到lookup执行完就提前执行了,导致了结果错误解决办法:是否可以把后面的结果显示纳入到工作线程呢?如下代码: private void searchButton_actionPerformed(){ outputTA.setText("Searching for: "+searchTF.getText()); final String[][] results=new String[1][1]; new Thread(){ public void run(){ results[0]=lookup(searchTF.getText()); outputTA.setText(""); for (int i = 0; i < results[0].length; i++) { String result = results[0][i]; outputTA.setText(outputTA.getText() + '\n' + result); } } }.start(); }问题:从事件派发线程之外的线程访问Swing组件是不安全的,让Swing组件的操作在工作线程中执行,这是危险的,违背了Swing的原则(只有从事件派发线程才能更新组件),也可能导致系统的错误解决办法:使用SwingUitilities类的invokeLater方法让后面的显示结果起一个新的线程操作排队等待lookup执行完成由Swing线程(事件派发线程)来执行,如下代码 private void searchButton_actionPerformed(){ outputTA.setText("Searching for: "+searchTF.getText()); final String[][] results=new String[1][1]; new Thread(){ public void run(){ results[0]=lookup(searchTF.getText()); /*下面需要更新UI,必须在Swing线程中执行,所以这里创建了一个新的线程, 由invokeLater等待lookup执行完成之后异步执行*/ SwingUtilities.invokeLater(new Runnable(){ public void run(){ outputTA.setText(""); for(int i=0;i<results[0].length;i++){ String result=results[0][i]; outputTA.setText(outputTA.getText()+'\n'+result); } } }); } }.start(); }以上基本解决了界面卡死和线程的问题,但可以看到代码的可读性和维护性都不太好。网上还其他解决办法,叫事件驱动,有兴趣可以去看看,这个方法当然会付出时间成本的代价 用wrapper启动java大概10个线程就崩掉了啊,然后参数调整了一大堆都不行啊。不知道方向~~~求助啊~ panle绘图与加组件问题 用java正则表达式匹配这个字符串(<?xml version="1.0" encoding="UTF-8"?>)请各位高手们帮忙 ArrayList问题 ▲★数据集 排序问题★▲ 求java实现的电梯算法(越完整越好,只是用来参考) 怎样把一个double数组写到文本文件里?(在线等待) 请问哪里有JDK1。3是帮助下载 紧急求助!!! 不信没人懂JAVA 这段简单的代码 大概执行什么? 有错的地方吗? 求一正则表达式
初始线程:用来创建GUI组件、资源加载和启动GUI组件,当UI出现之后,初始线程就完成了使命。
事件线程:即Swing线程、事件分派线程、AWT线程、Event Dispatch Thread。Swing所有组件的事件行为都交给这个线程进行处理,Swing线程是和Swing组件进行交互的唯一的线程,所有的绘制和图形、鼠标事件、组件事件、按钮事件和所有其他事件都发生在Swing线程。
工作线程:这是我们自己需要运行其他任务的线程,优秀的GUI程序绝不能让界面卡死,会让用户崩溃,所以这时候需要工作线程,也可以说是在背后运行的线程。使用多线程的优势:
1, 当有大量数据操作时,不让界面卡死;
2, 多线程可以提高性能,多个线程同时操作,能充分利用资源线程尽量要少用,原因如下:
1, 一个进程中的多个线程共享相同的内存地址控件,这就以为着他们可以访问相同的变量和对象,而且他们从同一个堆中分配对象,这里可能会造成线程的互相干扰。
2, 过度使用线程可能会危及程序的性能及其可维护性。与线程相关的API:Thread、Runnable、SwingUitilities
Thread:java提供的一个抽象类,该类里面有个一个抽象的run()方法,我们在写程序时,只要继承于这个类,实现run()方法就可以了,在程序中,如果我们想用另一个线程来执行一些动作,这要把这些动作的代码写在run()方法中,然后再调用从Thread类继承来的start()方法。如:
public class MyThread extends Thread{
static MyThread mt=new MyThread();
public static void main(String args[]){
mt.start();
for(int i=0;i<100;i++){
System.out.println("i=" +i);
}
}
public void run(){
for(int j=0;j<100;j++){
System.out.println("j= "+j);
}
}
}
Thread的其他方法:sleep()、stop()
Runnable:
Java提供了两种机制实现多线程,可以继承Thread类,也可以通过Runnable接口实现。public class RunnableDemo implements Runnable{
Thread thread2=new Thread(this,"2");
public void run() {
// TODO Auto-generated method stub
System.out.println("线程:"+thread2.getName()+"开始运行!");
for(char ch='A';ch<='Z';ch++){
System.out.println(ch);
try{
thread2.sleep(10);
}catch(InterruptedException e){
System.out.println("线程2异常");
}
} }
public static void main(String[] args){
Thread thread2=new Thread(new RunnableDemo());
thread2.start();
for(int i=0;i<100;i++){
System.out.println("i=" +i);
}
}
}
SwingUitilities:提供了两个方法invokeLater和invoteAndWait,他们都是使事件派发线程上的可运行对象排队。当可运行对象排在事件派发队列的队首时,就调用其run方法。其效果是允许事件派发线程调用另一个线程中的任意一个代码块。invokeandwait()方法阻塞直到runnnable执行完毕;invokelater()异步地执行runnable。invokeandwait()一般不赞成使用,因为它可能导致严重的线程死锁,对你的应用造成严重的破坏。所以,让我们把它放置一边,使用invokelater()方法。实例:
看下面这段代码的演变过程:目的是实现一个按钮的事件;文本框(searchTF)、按钮(searchButton)、输出文本区(outputTA);lookup是一个费时查询过程;
第一版本:
private void searchButton_actionPerformed(){
outputTA.setText("Searching for: "+searchTF.getText());
String[] results=lookup(searchTF.getText());
outputTA.setText("");
for (int i = 0; i < results.length; i++) {
String result = results[i];
outputTA.setText(outputTA.getText() +
'\n' + result);
}
}
问题:由于lookup比较费时,界面看上去像卡死了
解决办法:lookup这个非swing任务起一个工作线程,如下代码
private void searchButton_actionPerformed(){
outputTA.setText("Searching for: "+searchTF.getText());
final String[][] results=new String[1][1];
new Thread(){
public void run(){
results[0]=lookup(searchTF.getText());
}
}.start();
outputTA.setText("");
for (int i = 0; i < results[0].length; i++) {
String result = results[0][i];
outputTA.setText(outputTA.getText() +
'\n' + result);
}
}
问题:后面的结果显示将不会等到lookup执行完就提前执行了,导致了结果错误
解决办法:是否可以把后面的结果显示纳入到工作线程呢?如下代码:
private void searchButton_actionPerformed(){
outputTA.setText("Searching for: "+searchTF.getText());
final String[][] results=new String[1][1];
new Thread(){
public void run(){
results[0]=lookup(searchTF.getText());
outputTA.setText("");
for (int i = 0; i < results[0].length; i++) {
String result = results[0][i];
outputTA.setText(outputTA.getText() +
'\n' + result);
}
}
}.start();
}
问题:从事件派发线程之外的线程访问Swing组件是不安全的,让Swing组件的操作在工作线程中执行,这是危险的,违背了Swing的原则(只有从事件派发线程才能更新组件),也可能导致系统的错误
解决办法:使用SwingUitilities类的invokeLater方法让后面的显示结果起一个新的线程操作排队等待lookup执行完成由Swing线程(事件派发线程)来执行,如下代码
private void searchButton_actionPerformed(){
outputTA.setText("Searching for: "+searchTF.getText()); final String[][] results=new String[1][1]; new Thread(){
public void run(){
results[0]=lookup(searchTF.getText());
/*下面需要更新UI,必须在Swing线程中执行,所以这里创建了一个新的线程,
由invokeLater等待lookup执行完成之后异步执行*/
SwingUtilities.invokeLater(new Runnable(){
public void run(){
outputTA.setText("");
for(int i=0;i<results[0].length;i++){
String result=results[0][i];
outputTA.setText(outputTA.getText()+'\n'+result);
}
}
});
}
}.start();
}以上基本解决了界面卡死和线程的问题,但可以看到代码的可读性和维护性都不太好。网上还其他解决办法,叫事件驱动,有兴趣可以去看看,这个方法当然会付出时间成本的代价