博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
学习JAVA多线程程序设计(一)
阅读量:4039 次
发布时间:2019-05-24

本文共 5233 字,大约阅读时间需要 17 分钟。

 
【摘要】本系列文章主要探讨JAVA中的多线程程序设计,内容涉及使用线程的场合,线程的基本创建方法,管理线程的执行,在多线程进行程序设计时资源的访问控制方法以及应该避免发生的问题。线程池技术,用于减少线程创建的系统开销,并通过示例说明线程池的实现方式。
本文是系列文章的第一篇。
 
什么是线程?什么是进程?
这两个概念在程序设计开发过程中好像并不是很难区分,但是好像又不太容易准确的描述。
所谓进程,就是能够被操作系统控制,各自独立执行,拥有各自独立操作的内存空间和完整的处理数据的程序执行单元。进程之间会通过原始的机制相互通信。例如使用信号处理、共享内存,Socket机制、文件等手段交换信息。换句话说,进程就是能够独立执行的程序。
所谓线程,就是比进程划分的更细的程序执行单元,它们存在于某一个进程中,是进程的组成部分。在执行上,各个线程没有各自独立的完整的数据,他们共享数据,共享系统的状态,运行在同一个地址空间。线程也为多处理器系统中并行地使用硬件提供了一个分解,同一程序内多个线程可以在多CPU的情况下同时调度。
在使用JAVA语言编程时,没有显式的创建线程,有时候也会创建多线程应用程序。执行JAVA应用程序时,main()方法就是由一个线程执行的;另外,在使用JAVA Swing组件开发GUI程序时,都会显式地创建并使用另一个线程:AWT事件线程。
如何创建线程?
JAVA中创建新的线程非常简单。每个线程都由java.lang.Thread类的一个对象所表示,要创建线程对象,可以让用户创建的类继承Thread类即可。另外一种创建线程对象的方法是用户的类实现Runnable接口。Runnable接口中定义的惟一一个方法为run()方法,线程执行时调用该方法。线程一旦退出run()方法,线程就结束了。
 
创建线程示例一:
程序工作原理:用户自定义的TryThreadOne类继承Thread类,用户覆盖了Thread类中的run()方法,通过一个for循环输出一些内容,每执行一次输出,线程休眠1秒钟在转入就绪状态,等待再一次执行。在TryThreadOne类的构造方法中通过start()方法启动线程,该方法会调用run()方法执行。
/*
 * Author: seagal890
 * Date&Time: 2007-10-5
 * */
package
com.burke.example;
 
public
class
TryThreadOne
extends
Thread {
 
   
private
String
name
;
 
   
public
TryThreadOne(String name) {
      
this
.
name
= name;
      
this
.start();
    }
 
   
public
void
run() {
          
try
{
             
for
(
int
i = 0; i < 10; i++) {
              System.
out
.println(
name
+
" "
+i);
              Thread.sleep(1000);     
              }
           }
catch
(InterruptedException e) {
             
//
TODO
Auto-generated catch block
              e.printStackTrace();
           }
      
    }
 
   
/**
     
*
@param
args
     
*/
   
public
static
void
main(String[] args) {
      
//
TODO
Auto-generated method stub
       TryThreadOne app =
new
TryThreadOne(
"Thread "
);
      
    }
 
}
 
创建线程程序示例二:
程序工作原理:用户的类通过实现Runnable接口产生线程对象。用户的类通过覆盖掉Runnable接口中的run()方法实现输出任务。在创建线程对象时,需要首先创建TryThreadTwo类的对象app,然后再将该app对象传递给Thread类的构造方法,构造出一个线程对象
myThread
,通过
start()
方法启动线程执行。
Start()
方法会自动地去调用
run()
方法执行。
/*
 * Author: seagal890
 * Date&Time: 2007-10-5
 * */
package
com.burke.example;
 
public
class
TryThreadTwo
implements
Runnable{
 
   
private
String
name
;
   
   
public
TryThreadTwo(String name){
      
this
.
name
=name;
    }
   
   
public
void
run(){
      
try
{
          
for
(
int
i = 0; i < 10; i++) {
           System.
out
.println(
name
+
" "
+i);
           Thread.sleep(1000);     
           }
       }
catch
(InterruptedException e) {
          
//
TODO
Auto-generated catch block
           e.printStackTrace();
       }
    }
   
/**
     
*
@param
args
     
*/
   
public
static
void
main(String[] args) {
      
//
TODO
Auto-generated method stub
       TryThreadTwo app=
new
TryThreadTwo(
"Thread testing "
);
       Thread myThread=
new
Thread(app);
       myThread.start();
    }
 
}
 
创建线程程序示例三:主线程和子线程交替执行。
程序工作原理:通过
NewThread
继承
Thread
类创建线程对象——这是一个子线程对象。子线程执行的特点是在循环执行
5
次,每执行一次休眠
1
秒钟。在包含
main()
方法的
ExtendThread
类中,创建该
NewThread
类的对象,然后通过循环让主线程执行
5
次,主线程每执行一次,休眠
5
秒钟后再执行。主线程和子线程交替执行,先执行一次子线程的输出,然后执行主线程的输出。子线程执行完毕后,主线程还需要继续执行,直到主线程中的
for
循环执行完毕为止。
/*
 * Author: seagal890
 * Date&Time: 2007-10-5
 * */
 
package
com.burke.example;
 
public
class
NewThread
extends
Thread{
 
   
public
NewThread(){
      
super
(
"Demo Thread"
);
       System.
out
.println(
"Child Thread: "
+
this
);
       start();
    }
   
   
public
void
run(){
      
try
{
          
for
(
int
i=5;i>0;i--){
              System.
out
.println(
"Chile Thread: "
+i);
              Thread.sleep(1000);
           }
       }
catch
(InterruptedException e){
           System.
out
.println(
"Child Thread Interrupted!"
);
       }
       System.
out
.println(
"Exiting Child Thread"
);
    }
}
 
 
package
com.burke.example;
 
public
class
ExtendThread{
   
public
static
void
main(String args[]){
      
new
NewThread();
      
      
try
{
          
for
(
int
i=5;i>0;i--){
              System.
out
.println(
"Main Thread: "
+i);
              Thread.sleep(5000);
           }
       }
catch
(InterruptedException e){
           System.
out
.println(
"Main Thread Interrupted!"
);
       }
       System.
out
.println(
"Exiting Main Thread!"
);
    }
}
 
             
创建线程程序示例三:在GUI程序中使用线程对象控制按钮的状态
程序工作原理:点击按钮时,线程对象开始执行,在程序控制台(后台)执行打印输出,同时按钮的标题变为“线程处理中,请等待…”,按钮的状态变为不可用状态。等待线程执行完毕,按钮的标题变为“
线程执行完毕”,同时按钮的状态又恢复为可用状态。
package
com.burke.example;
 
import
java.awt.Container;
import
java.awt.event.ActionEvent;
import
java.awt.event.ActionListener;
 
import
javax.swing.JButton;
import
javax.swing.JFrame;
 
public
class
MyFrameDemo
extends
JFrame {
    Container
content
;
    JButton
myBtn
;
   
public
MyFrameDemo() {
      
this
.setTitle(
"
线程测试
"
);
      
this
.setBounds(150,100,400,300);
      
content
=
this
.getContentPane();
      
content
.setLayout(
null
);
      
myBtn
=
new
JButton(
"
测试线程计算
,
点击开始执行
"
);
      
myBtn
.setBounds(100,100,200,30);
      
myBtn
.addActionListener(
             
new
ActionListener(){
                 
public
void
actionPerformed(ActionEvent e){
                    
myBtn
.setEnabled(
false
);
                     Thread t=
new
Thread(
                           
new
Runnable(){
                               
public
void
run(){
                                  
try
{
                                      
for
(
int
i=0;i<10;i++){
                                         
myBtn
.setEnabled(
false
);
                                         
myBtn
.setText(
"
线程执行中,请等待
..."
);
                                          System.
out
.println(
"testing "
+i);
                                          Thread.sleep(1000);
                                         
                                       }
                                   }
catch
(InterruptedException e){
                                       e.printStackTrace();
                                   }
                                  
myBtn
.setText(
"
线程执行完毕
"
);
                                  
myBtn
.setEnabled(
true
);
                                }
                            }
                     );
                     t.start();
                    
                    
                  }
              }
       );
      
content
.add(
myBtn
);
      
this
.setDefaultCloseOperation(JFrame.
EXIT_ON_CLOSE
);
      
this
.setVisible(
true
);
      
    }
   
   
public
static
void
main(String args[]){
       MyFrameDemo app=
new
MyFrameDemo();
    }
}
 
通过上面的几个例子,我们看到了在程序中如何创建线程对象和启动线程对象。一个线程对象的生命周期内需要经历创建、就绪、运行、阻塞/休眠、死亡等几种状态。线程可以在各个不同状态之间进行转换。
对线程的状态控制
start()方法可以启动线程对象,去调用run()方法,使得线程处于运行状态。
sleep()方法会导致当前线程等待指定的一段时间,在转入就绪状态,而不会消耗过多的CPU时间。
Join()方法,如果一个线程中需要等待另一个线程消亡,可以调用join()方法来处理希望消亡的线程。无参数的调用join()方法将暂停当前的线程,直到指定的线程消亡。
线程的调度
线程的调度在一定程度上决定于操作系统,但每个线程在其他线程调用sleep()方法而休眠时都有机会执行。如果操作系统采用抢占式的任务调度,不在run()方法中调用sleep()方法,程序也能运行。但是,如果操作系统不是以这种方式调度的,即在run()方法中不调用sleep()方法,第一个线程就会独占处理器并无限地运行下去。
 
在使用多线程技术编写程序时,对于产生的多个线程进行有效的管理,是一个比较复杂的问题,我将在后面一篇文章中探讨对于多线程的管理问题。
 
 

转载地址:http://pavdi.baihongyu.com/

你可能感兴趣的文章
selenium学习资料
查看>>
<转>文档视图指针互获
查看>>
Matlab subplot 图像间距调整
查看>>
从mysql中 导出/导入表及数据
查看>>
HQL语句大全(转)
查看>>
几个常用的Javascript字符串处理函数 spilt(),join(),substring()和indexof()
查看>>
javascript传参字符串 与引号的嵌套调用
查看>>
swiper插件的的使用
查看>>
layui插件的使用
查看>>
JS牛客网编译环境的使用
查看>>
9、VUE面经
查看>>
关于进制转换的具体实现代码
查看>>
洛谷 P1848
查看>>
BZOJ 2669
查看>>
小W走迷宫
查看>>
高精度四则运算模板
查看>>
BZOJ 2653
查看>>
HDU 5283
查看>>
BZOJ 4554
查看>>
51 nod 1775 LIS Counting
查看>>