课程  Java面向对象程序设计

一、实验目的

掌握多线程程序设计

二、实验环境

1、微型计算机一台

2、WINDOWS操作系统,Java SDK,Eclipse开发环境

三、实验内容

1、Java有两种实现多线程的方式:通过Runnable接口、通过Thread直接实现,请掌握这两种实现方式,并编写示例程序。

2、多线程是并发执行的,交替占有cpu执行,请编写示例程序,并观察输出结果。

3、编写程序实现生产者消费者问题代码,采用线程同步机制来解决多线程共享冲突问题。

四、实验步骤和结果

1、Java有两种实现多线程的方式:通过Runnable接口、通过Thread直接实现,请掌握这两种实现方式,并编写示例程序。

(1)通过Runnable接口实现多线程:

定义实现java.lang.Runnable接口的类,Runnable接口中只有一个run()方法,用来定义线程运行体。代码(MyRunner.java)如下:

package CreateThread;
import java.util.TreeMap; public class MyRunner implements Runnable{ //实现Runnable接口
public void run(){
for (int i = 0; i <20; i++) { //要在线程中执行的代码
System.out.println("MyRunner:"+i);
}
}
public static void main(String[] args) {
Thread thread1=new Thread(new MyRunner());
thread1.start();
}
}

程序执行结果截图如下:

(2)通过Thread实现多线程:将类定义为Thread类的子类,并重写run()方法。代码(MyThread.java)如下

package CreateThread;
public class MyThread extends Thread {
public void run(){
for (int i = 0; i < 10; i++) {
System.out.println("MyThread:"+i);
}
}
public static void main(String[] args) {
Thread thread2=new MyThread();
thread2.start();
}
}

2、多线程是并发执行的,交替占有cpu执行,编写示例程序如下,主线程先执行,然后启动两个新线程,但这两个新线程并没有立刻得到执行,而是统一由JVM根据时间片来调度,调度到哪个线程,就由哪个线程执行片刻。并且这两个新线程应该是交替显示结果,如果没有交替显示,可能是机器性能较好,在单位时间片内已经完成了循环运算,我们可以将循环次数更改为2000或更高值再行测试。多运行几次,每次的输出结果都不可能相同,说明JVM调度线程的执行顺序是随机的。

测试代码(ConcurrentExecutionThread.java)如下所示:

package CreateThread;
public class ConcurrentExecutionThread {
public static void main(String[] args) {
System.out.println("主线程开始执行");
Thread thread1=new Thread(new MyRunner());
thread1.start();
System.out.println("启动一个新线程(thread1)..."); Thread thread2=new MyThread();
thread2.start();
System.out.println("启动另一个新线程(thread2)...");
System.out.println("主线程执行完毕");
}
}

程序运行结果为:

3、编写程序实现生产者消费者问题代码,采用线程同步机制来解决多线程共享冲突问题。

(1)编写产品类

生产者要生产产品,消费者要消费产品,所以产品要提供一个含有标识的id属性,另外要在生产或消费时打印产品的详细内容,所以需要重写toString()方法,产品类(Products.java)代码如下:

package SynchronizedThread;
//编写产品类
public class Products {
int id;
public Products() {
super();
}
public Products(int id) {
super();
this.id = id;
}
public String toString() {
return "Products [id=" + id + "]";
}
}

(2)编写店员类(Clerk.java)

店员一次只能持有10份产品,如果生产者生产的产品多于10份,则会让当前的正在此对象上操作的线程等待。一个线程访问addProduct方法时,它已经拿到这个锁了,当遇到产品大于10份时,它会阻塞。而且,只有锁定对象后才可以用wait方法,否则会出错。并且,notify与wait一般是一一对应的。

package SynchronizedThread;
//编写店员类
public class Clerk {
int index=0;//默认为0个产品
Products[] pro=new Products[10];
//生产者生产出来的产品交给店员
public synchronized void addProduct(Products pd){
while (index==pro.length) {
try {
this.wait();//产品已满,请稍后再生产
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();//通知等待区的消费者可以取产品了
pro[index]=pd;
index++;
}
//消费者从店员处取产品
public synchronized Products getProduct(){
while (index==0) {
try {
this.wait(); //缺货,请稍后再取。
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();//通知等待区的生产者可以生产产品了
index--;
return pro[index];
}
}

(3)编写生产者线程类(Producer.java)

生产者与店员有关系,所以店员类被当做属性引入进来,通过构造器完成初始化店员类对象的任务。为了凸显效果,每生产一个产品后让线程睡眠一会儿。

package SynchronizedThread;
//编写生产者线程类
public class Producer implements Runnable { //生产者线程要执行的任务
private Clerk clerk;
public Producer() {
super();
}
public Producer(Clerk clerk) {
super();
this.clerk = clerk;
}
public void run() {
System.out.println("生产者开始生产产品");
for (int i = 0; i <15; i++) {//注意此处的循环次数一定要大于pro数组的长度(10)
Products pd=new Products(i);
clerk.addProduct(pd);//生产产品
System.out.println("生产了:"+pd);
try { //睡眠时间用随机产生的值来设置
Thread.sleep((int)(Math.random()*10)*100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

(4)编写消费者线程类(Consumer.java)

消费者与店员也有关系,所以店员类被当做属性引入进来,同样通过构造器完成初始化店员类对象的任务。

package SynchronizedThread;
//编写消费者线程类
public class Consumer implements Runnable {//消费者线程要执行的任务
private Clerk clerk;
public Consumer() {
super();
}
public Consumer(Clerk clerk) {
super();
this.clerk = clerk;
}
public void run() {
System.out.println("消费者开始取走产品");
for (int i = 0; i <15; i++) {//注意此处的循环次数一定要大于pro数组的长度(10)
//取产品
Products pd=clerk.getProduct();
System.out.println("消费了:"+pd);
try { //睡眠时间用随机产生的值来设置
Thread.sleep((int)(Math.random()*10)*100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

(5)编写生产者消费者问题的测试类( ProducerAndConsumerTest.java)

创建生产者和消费者线程,然后分别调度线程。

package SynchronizedThread;
//生产者消费者问题测试
public class ProducerAndConsumerTest {
public static void main(String[] args) {
Clerk clerk=new Clerk();
Thread producerThread=new Thread(new Producer(clerk));//创建生产者线程
Thread consumerThread=new Thread(new Consumer(clerk));//创建消费者线程
producerThread.start();
consumerThread.start();
}
}

(6)运行程序,在控制台得到的输出结果如下所示:

五、实验总结

1.本次实验按时按量完成。

2.线程和进程的区别:

在操作系统中能同时运行多个任务(程序)叫做多进程;在同一应用程序中多条执行路径并发执行叫做多线程。

(1)每个进程都有独立的代码和数据空间(进程上下文),进程间的切换开销大。

(2)同一进程内的多个线程共享相同的代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程间的切换开销小。

通常,在以下情况中可能要使用到多线程:

(1)程序需要同时执行两个或多个任务。

(2)程序需要实现一些需要等待的任务时,如用户输入、文件读写操作、网络操作、搜索等。

(3)需要一些后台运行的程序时。

3.线程同步的方法:为了共享区域的安全,可以通过关键字synchronized来加保护伞,以保证数据的安全。synchronized主要应用于同步代码块和同步方法中。

(1) 同步方法:synchronized放在方法声明中,表示整个方法为同步方法。

(2) 同步代码块:把线程体内执行的方法中会操作到共享数据的语句封装在{}之内,然后用synchronized放在某个对象前面修饰这个代码块。

如果一个线程调用了synchronized修饰的方法,它就能够保证该方法在执行完毕前不会被另一个线程打断,这种运行机制叫作同步线程机制。

4.在生产者线程类与消费者线程类中,设置让线程睡眠的时间如果是一样的,运行结果中会出现“生产一个消费一个,生产与消费时成对出现的“的这个不符合现实的现象。这时需要修改线程的睡眠时间,把睡眠时间用随机产生的值来设置。这样之后,再次运行程序,可以看到有时候生产了多个产品后,消费者才开始消费。

Normal
0

7.8 磅
0
2

false
false
false

EN-US
ZH-CN
X-NONE

MicrosoftInternetExplorer4

 

/* Style Definitions */
table.MsoNormalTable
{mso-style-name:普通表格;
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-qformat:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin:0cm;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.5pt;
mso-bidi-font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-fareast-font-family:宋体;
mso-fareast-theme-font:minor-fareast;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;
mso-font-kerning:1.0pt;}

Java 多线程程序设计的更多相关文章

  1. Java多线程程序设计详细解析

    一.理解多线程 多线程是这样一种机制,它允许在程序中并发执行多个指令流,每个指令流都称为一个线程,彼此间互相独立. 线程又称为轻量级进程,它和进程一样拥有独立的执行控制,由操作系统负责调度,区别在于线 ...

  2. Java多线程_复习(更新中!!)

    java多线程的常见例子 一.相关知识: Java多线程程序设计到的知识: (一)对同一个数量进行操作 (二)对同一个对象进行操作 (三)回调方法使用 (四)线程同步,死锁问题 (五)线程通信 等等 ...

  3. java多线程编程

    一.多线程的优缺点 多线程的优点: 1)资源利用率更好2)程序设计在某些情况下更简单3)程序响应更快 多线程的代价: 1)设计更复杂虽然有一些多线程应用程序比单线程的应用程序要简单,但其他的一般都更复 ...

  4. Java 多线程——基础知识

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  5. 从JAVA多线程理解到集群分布式和网络设计的浅析

    对于JAVA多线程的应用非常广泛,现在的系统没有多线程几乎什么也做不了,很多时候我们在何种场合如何应用多线程成为一种首先需要选择的问题,另外关于java多线程的知识也是非常的多,本文中先介绍和说明一些 ...

  6. 学习笔记之JAVA多线程

    Java程序设计实用教程 by 朱战立 & 沈伟 孙鑫Java无难事 Java 多线程与并发编程专题(http://www.ibm.com/developerworks/cn/java/j-c ...

  7. java多线程 并发 编程

    转自:http://www.cnblogs.com/luxiaoxun/p/3870265.html 一.多线程的优缺点 多线程的优点: 1)资源利用率更好 2)程序设计在某些情况下更简单 3)程序响 ...

  8. Java多线程编程中Future模式的详解

    Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...

  9. Java多线程与并发模型之锁

    这是一篇总结Java多线程开发的长文.文章是从Java创建之初就存在的synchronized关键字引入,对Java多线程和并发模型进行了探讨.希望通过此篇内容的解读能帮助Java开发者更好的理清Ja ...

随机推荐

  1. [zz]论程序员

    g9老大多年前的趣文: 论程序员 根据钱钟书先生的<论文人>胡改的.聊搏一笑,文责不负.程序员是可嘉奖的,因为他虚心,知道上进,并不拿身分,并不安本分.真的,程序员对于自己,有时比旁人对于 ...

  2. 10年省赛-Greatest Number (二分+暴力) + 12年省赛-Pick apples(DP) + UVA 12325(暴力-2次枚举)

    题意:给你n个数,在里面取4个数,可以重复取数,使和不超过M,求能得到的最大的数是多少: 思路:比赛时,和之前的一个题目很像,一直以为是体积为4(最多选择四次)的完全背包,结果并不是,两两求和,然后二 ...

  3. 前App Store高管揭秘:关于“苹果推荐”的七大真相

    相信你已经看过很多这样那样关于如何获得苹果商店推荐的攻略了,但其实很多人依然陷入了很大的误区.前不久采访了前App Store团队高管Greg Essig,向各位开发者揭示关于获得苹果推荐的真相. 在 ...

  4. C语言----变量及作用域 、 指针 、 指针和数组 、 进程空间 、 字符串

    1 使用程序来模拟放球.取球的问题 1.1 问题 栈是一种特殊的线性表,它的逻辑结构和线性表相同,只是其运算规则较线性表有更多的限制,故又称为运算受限的线性表. 栈的定义是限制仅在表的一端进行插入和删 ...

  5. cJSON_hacking

    /****************************************************************************** * cJSON_hacking * * ...

  6. native

    源博客:http://blog.csdn.net/jiakw_1981/article/details/3073613 一. 什么是Native Method   简单地讲,一个Native Meth ...

  7. Condition的await-signal流程详解(转)

    上一篇文章梳理了condtion,其中侧重流程,网上看到这篇文章文章介绍的很细.值得学习.特意转载过来.   转载请注明出处:http://blog.csdn.net/luonanqin 转载路径:h ...

  8. 什么是JavaScript闭包终极全解之一——基础概念

    本文转自:http://www.cnblogs.com/richaaaard/p/4755021.html 什么是JavaScript闭包终极全解之一——基础概念 “闭包是JavaScript的一大谜 ...

  9. OpenFlow Switch学习笔记(一)——基础概念

    OpenFlow Switch v1.4.0规范是在2013年10月14号发布,规范涵盖了OpenFlow Switch各个组件的功能定义.Controller与Switch之间的通信协议Open F ...

  10. Handler 引起的内存泄露

    先看一组简单的代码 1 2 3 4 5 6 7 8 9 public class SampleActivity extends Activity { private final Handler mHa ...