一、 简答题
1.什么叫线程?什么叫多线程?
答:线程是一个程序内部的一条执行线路,一个比进程更小的能独立运行的基本单位。多线程是指一个程序中同时存在着好几个执行体,它们按几条不同的执行线路共同工作,独立完成各自的功能而互不干扰
2.进程和线程的区别是什么?
答:它们的区别在于:
进程是程序的一次动态执行过程,它对应了从代码加载,执行到执行完毕的一个完整过程,这个过程也是进程本身从产生、发展到消亡的过程。线程是比进程更小的执行单位。一个进程在其执行过程中,可以产生多个线程,形成多条执行线路。每条线路,即每个线程也有它自身的产生、存在和消亡的过程,也是一个动态的概念。
每个进程都有独立的代码和数据空间,进程间切换的开销大;而同一类线程可以共享代码和数据空间,但每个线程有独立的运行栈和程序计数器,线程切换的开销小。
3.简述线程的生命周期。
答:新建的线程在它完整的生命周期中,包括新建、就绪、运行、阻塞和死亡5种状态。
(1)新建(new)状态,用new命令建立一个线程后,还没有启动其指定的指令序列,这时的线程状态就是新建状态。
(2)就绪(Runnable)状态,也叫做可运行状态,处于新建状态的线程被启动后即进入了本状态。这时线程正在等待分配CPU资源,一旦获得CPU资源即进入了自动运行状态。
(3)运行(running)状态,线程获得了CPU资源正在线程的指令,此时除非它自动放弃CPU资源或者有更加高优先级的线程进入,否则线程将一直运行到结束。
(4)阻塞(blocked)状态,由于某种原因致使正在运行的线程让出CPU资源暂停自己的执行,即进入阻塞状态,这时只有引起线程堵塞的原因被消除后才能使本线程回到就绪状态。
(5)死亡(dead)状态,处于死亡状态的线程不具备继续运行的能力,死亡的原因有两个:一个是正常的线程完成了它的全部任务后退出,另一种是线程被强制中止,如调用stop( )或destroy( )方法让线程消亡。此时线程不可能再进入就绪状态等待执行。
4.在Java语言中创建线程有几种方式?它们有何区别?
答:在Java语言中创建线程有两种方式:一种是创建Thread类的子类,另一种是实现Runnable接口,两种创建方式的区别在于:
直接继承Thread类创建线程时,Thread子类无法再从其他类继承。
使用Runnable接口创建线程时可以将代码和数据分开,形成清晰的模型。线程体run( )方法所在的类还可以从其他类继承一些有用的属性或方法,并有利于保持程序风格的一致性。
5.Java线程的优先级设置遵循什么原则?
答:Java线程的优先级设置遵从下述原则:
(1) 线程创建时,子线程继承父线程的优先级
(2) 线程创建后,可在程序中通过调用setPriority( )方法改变线程的优先级
(3) 线程的优先级是1~10之间的正整数,数字越大优先级越高,默认的优先级是居中,即为5。
6.举例说明什么叫线程的同步?Java中如何实现线程的同步?
答:当在一个程序中使用两个或多个线程时,可能会发生多个线程同时要访问同一资源的情况。例如,一个线程可能尝试从一个文件中读取数据,而另一个线程则尝试在同一文件中修改数据。在这种情况下,数据可能会变得不一致。我们需要做的是允许一个线程彻底完成其任务后,再允许下一个线程执行。必须保证一个共享的资源一次只被一个线程使用。实现此目的的过程称为“同步”。
可以用两种方法实现同步:
同步方法:通过在方法声明中加入synchronized关键字可以声明要同步方法
同步块:通过synchronized关键字将一个程序块声明为同步代码块
二、 编程题
1.编写一个程序,通过继承Thread创建线程并以此生成两个线程,每个线程输出从1到5的数。
//参考答案1
public class XT010201 extends Thread{
public static void main(String args[]){
new XT010201();
}
public XT010201(){
Thread t1=new Thread(this);
t1.setName("线程1 ");
Thread t2=new Thread(this);
t2.setName("线程2 ");
t1.start();
t2.start();
}
public void run(){
//System.out.println(Thread.currentThread().getName());
for(int i=1;i<=100;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}
//参考答案2
class MyThread extends Thread {
public MyThread(String name) {
this.setName(name);
}
public void run(){
for(int i=1;i<=100;i++){
System.out.println(Thread.currentThread().getName()+i);
}
}
}
public class XT010201 {
public static void main(String args[]){
MyThread t1=new MyThread("线程1 ");
MyThread t2=new MyThread("线程2 ");
t1.start();
t2.start();
}
}
2.创建一个名称为Myapplet的Applet,通过实现Runnable接口为其提供多线程的功能。在Applet中输出从1到20的数字,且每个数字间延迟300毫秒。
import java.awt.*;
import java.applet.*;
public class XT010202 extends Applet implements Runnable{
int i;
Thread t;
public void init() {
t=new Thread(this);
t.start();
}
public void run() {
for(i=1;i<=20;i++){
try {
repaint();
Thread.sleep(300);
}
catch(InterruptedException e){
System.out.println(e);
}
}
}
public void paint(Graphics g){
g.drawString("i等于"+i,30,30);
}
}
<HTML>
<HEAD>
<TITLE> 一个具有多线程能力的Applet小程序</TITLE>
</HEAD>
<BODY>
<applet code = XT010202.class WIDTH = 200 HEIGHT = 200 >
</applet>
</BODY>
<HTML>
3.编写程序,通过多线程实现电子实钟的功能。程序的运行结果如图10-6所示。
import java.awt.*;
import java.util.Calendar;
public class XT0102031 {
public static void main(String args[]) {
Label l = new Label();
Frame f=new Frame("电子时钟");
f.add(l);
f.setSize(150,100);
f.setVisible(true);
new SetTime(l).start();
while (true) {}
}//end main()
}//end class
class SetTime extends Thread {
String hour,minute,second;
Label l;
SetTime(Label l) {
this.l = l ;
}
public void run() {
while(true) {
Calendar c = Calendar.getInstance();
if (c.get(Calendar.HOUR_OF_DAY)<10)
hour="0" + c.get(Calendar.HOUR_OF_DAY);
else
hour=""+c.get(Calendar.HOUR_OF_DAY);
if (Calendar.MINUTE<10)
minute="0"+c.get(Calendar.MINUTE);
else
minute=""+c.get(Calendar.MINUTE);
if (c.get(Calendar.SECOND)<10)
second="0"+c.get(Calendar.SECOND);
else
second=""+c.get(Calendar.SECOND);
l.setText(hour+":"+minute+":"+second);
try {
Thread.sleep(1000);
} catch (InterruptedException e){}
}//end while
}
}
4.编写一个创建三个线程对象的程序。每个线程应该输出一则消息,并且消息后紧跟字符串“消息结束”。要求:在线程输出消息后,暂停一秒钟后才输出“消息结束”。输出结果如图10-7所示。
public class XT010204{
public static void main(String args[]) {
PrintMessage PM = new PrintMessage();
Thread t1=new Thread(PM);
Thread t2=new Thread(PM);
Thread t3=new Thread(PM) ;
t1.setName("这是消息1");
t2.setName("这是消息2");
t3.setName("这是消息3");
t1.start();
t2.start();
t3.start();
}
}
class PrintMessage implements Runnable{
String msg="";
public synchronized void run() {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {}
System.out.println("消息结束");
}
}
//修改书上例题10-4
//用同步方法实现
public class ThreadSyncDemo1 {
public static void main(String[] args) {
ThreadTest1 t=new ThreadTest1();
new Thread(t,"售票窗口1 ").start();//本线程调用同步代码块
new Thread(t,"售票窗口2 ").start();//本线程调用同步函数
}
}
class ThreadTest1 implements Runnable{
private int tickets=100;
public void run() {
while ( true ) {
sale();
}
}
public synchronized void sale() {
if ( tickets > 0 ) {
try {
Thread.sleep(10);
}
catch(Exception e){System.out.println(e.getMessage());}
System.out.println(Thread.currentThread().getName()+"正在卖第"+tickets--+"号票");
}
}
}//end class ThreadTest1
//修改书上例题10-4
//用同步代码块实现
public class ThreadSyncDemo2 {
public static void main(String[] args) {
ThreadTest2 t=new ThreadTest2();
new Thread(t,"售票窗口1 ").start();
new Thread(t,"售票窗口2 ").start();
}
}
class ThreadTest2 implements Runnable{
private int tickets=100;
public void run() {
while ( true ) {
sale();
}
}
public void sale() {
synchronized ( this ) {
if ( tickets > 0 ) {
System.out.println(Thread.currentThread().getName()+"正在卖第"+tickets+"号票");
try {
Thread.sleep( 10 );
}
catch(Exception e){System.out.println(e.getMessage());}
tickets--;
}
}//synchronized
}
}//end class ThreadTest2