实验八: 下载本文

实验八:多线程

一.实验目的

1.掌握通过Thread类和Runnable接口创建线程的方法

2.学会如何实现多线程的资源共享和通信,及如何控制线程的生命

3.在实际运用中,注意线程安全问题,掌握线程同步的方法,还应该理清程序逻辑,避免死锁

4.掌握线程优先级的概念,明白基于优先级的线程调度的基本规则

二.实验内容

2.1 巩固与理解

1.运行下面的程序,理解用创建Thread子类的方法实现多线程。 class SimpleThread extends Thread { public SimpleThread(String str) { super(str); }

public void run() {

for (int i = 0; i < 10; i++) {

System.out.println(i + \ try {

sleep((int)(Math.random() * 1000)); } catch (InterruptedException e) {} }

System.out.println(\ } }

public class TwoThreadsTest {

public static void main (String[] args) {

new SimpleThread(\ new SimpleThread(\ } }

2.运行下面的程序,理解用实现Runnable接口的方法实现多线程。 //这是一个时钟Applet,它显示当前时间并逐秒进行更新。 import java.awt.*; import java.applet.*; import java.util.*;

public class Clock extends Applet implements Runnable{ Thread clockThread; public void start( ){

1

if(clockThread==null){

clockThread=new Thread(this,\ clockThread.start(); } }

public void run(){

while(clockThread !=null){ repaint( ); try{

clockThread.sleep(1000); }catch(InterruptedException e){} } }

public void paint(Graphics g){ Date now=new Date();

g.drawString(now.getHours()+\5,10); }

public void stop(){

clockThread.stop(); clockThread=null; } }

? 编写HTML文件Clock.html:

? 运行Applet小程序,查看结果。

2.2 上机实验

1. 编写多线程程序模拟左右手轮流写字。 2. 编写一个类MyThread,它继承自Thread类:类中定义一个长整型变量delay;还定义有两个参数的构造方法,第1个参数str是String类型,通过super(str)调用父类构造方法给线程命名,第2个参数delay是长整型,用来初始化类中的变量delay。MyThread类中的run方法如下实现:循环3次,每次先在命令行输出线程第几次运行,然后休眠delay毫秒,循环结束后输出该线程结束的信息。编写应用程序TestThread.java,在其main方法中创建MyThread类的三个对象t1、t2、t3,分别指定线程名字为“线程A”、“线程B”和“线程C”,休眠时间为1000毫秒、2000毫秒、3000毫秒,并启动这三个线程,main方法的最后输出当前活动线程的数目。

3. 采用Java多线程技术编写程序,其中包括两个线程:A和B,其中A线程准备休眠一小时,B线程每隔一秒输入3句“起床”后,吵醒休眠的线程A。(25分)

2

4. 编写自定义类MyRunnable,该类实现Runnable接口,类中只有一个long类型变量delay,该类的构造函数有一个参数,用来初始化delay。类中的run方法如下实现:循环3次,每次先在命令行输出该线程第几次运行,然后休眠delay毫秒,循环结束后输出该线程结束的信息。编写应用程序TestRunnable.java,在其main方法中创建类MyRunnable类的三个对象r1、r2、r3,构造方法的参数分别指定为:1000、2000、3000。用线程类的构造方法Thread(Runnable target )创建3个线程,其参数分别为r1、r2、r3,并启动这三个线程,main方法的最后输出当前活动线程的数目。

5. 编写一个堆栈类MyStack,类中定义含5个元素的整型数组,并定义了两个同步(synchronized)方法:入栈操作方法push(int k),用来向堆栈中压入一个整数;出栈操作方法int pop( ),用来从栈顶弹出一个整数。方法push和pop中,通过wait()方法和notify()方法协调压入和弹出操作,例如,如果堆栈中没有数据则不能进行弹出操作,如果堆栈中压入的数据已有5个,则不能再进行压栈操作。此外编写两个线程子类Producer和Consumer,分别操作MyStack类对象,分别进行20次压入(压入的整数依次是1、2、…、20)和弹出操作,每次操作的结果显示再命令行界面。编写应用程序Test.java,创建一个MyStack类对象mystack,它是Producer线程和Consumer线程的共享数据源,创建和启动Producer线程和Consumer线程,对堆栈中的数据进行压入和弹出操作,观察程序的输出结果,理解线程之间的同步处理。

三.思考题

1.简述并区分程序、进程和线程三个概念。

2.线程有哪几个基本的状态?Java中线程调度遵循何种原则? 3.实现多线程可以用哪两种基本方法?将这两种方法进行比较。

四.实验报告内容

(1) 实验内容 (2) 实验目的 (3) 实验步骤 (4) 遇到的问题

(5) 实验结果与实验心得

3