实验5 多线程编程和集合框架

1.实验目的

(1)掌握Java多线程的概念和实现

(2)掌握Java多线程的同步问题

(3)掌握集合框架的知识,学会使用Arraylist<E>,LinkedList<E>和HashMap<K,V>类, HashSet<E>类。

2.实验要求

在Eclipse下创建Practice5项目,对未有包名要求的题目统一按照实验题名建包,然后将本题源代码 放在同一包下。对有包名要求的题目按照要求建包。作业提交时将Practice5项目下src文件包命名为Practice5.src压缩后提交。

3.实验题目

Exer1: 假设我们赋予每个线程一个唯一的编号,每次线程运行时打印其编号10次。定义测试类,在测试类中创建3个上述线程,并调用start()方法开始运行,观察运行结果;如果每个线程中的迭代次数增加至100次,观察结果,理解线程的并发处理;如果调用方法改为run(),运行结果会变化吗?

package Exer1;

public class print extends Thread {
   public void run() {
	   for(int i =1;i<=100;i++) {
		   System.out.println("打印编号"+Thread.currentThread().getName()+"第"+i+"次。");
	   }
   }
}
package Exer1;

public class Exer1 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
         print print1 = new print();
         print print2 = new print();
         print print3 = new print();
         print1.setName("一");
         print2.setName("二");
         print3.setName("三");
         print1.start();
         print2.start();
         print3.start();
	}

}

编译运行

 

Exer2:完成 P394编程题(1)。

package Exer2;

public class TicketHouse implements Runnable{
	int fiveAmount = 3,tenAmount=0,twentyAmount = 0;
    public void run() {
    	if(Thread.currentThread().getName().equals("张某")) {
    		salesTicket(20);
    	}
    	else if(Thread.currentThread().getName().equals("李某")) {
    		salesTicket(10);
    	}
    	else if(Thread.currentThread().getName().equals("赵某")) {
    		salesTicket(5);
    	}
    }
    private synchronized void salesTicket(int money) {
    	if(money == 5) {
    		fiveAmount = fiveAmount+1;
    		System.out.println("给"+Thread.currentThread().getName()+"入场券,"+Thread.currentThread().getName()+"的钱正好");
    	}
    	else if(money == 10) {
    		while(fiveAmount<1) {
    			try {System.out.println("\n"+Thread.currentThread().getName()+"靠边等...");
    			     wait();
    			     System.out.println("\n"+Thread.currentThread().getName()+"继续买票");
    			}
    			catch(InterruptedException e) {}
    		}
    		fiveAmount = fiveAmount-1;
    		tenAmount = tenAmount+1;
    		System.out.println("给"+Thread.currentThread().getName()+"入场券,"+Thread.currentThread().getName()+
    				"给10元,找赎5元");
    		
        }else if(money == 20) {
    		while(fiveAmount<3) {
    			try {System.out.println("\n"+Thread.currentThread().getName()+"靠边等...");
    			     wait();
    			     System.out.println("\n"+Thread.currentThread().getName()+"继续买票");
    			}
    			catch(InterruptedException e) {}
    		}
    		fiveAmount = fiveAmount-3;
    		twentyAmount = twentyAmount+1;
    		System.out.println("给"+Thread.currentThread().getName()+"入场券,"+Thread.currentThread().getName()+
    				"给20元,找赎15元");
    		
        }
    	notifyAll();
    }
}
package Exer2;

public class Exer2 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
        TicketHouse officer = new TicketHouse();
        Thread zhang,li,zhao;
        zhang = new Thread(officer);
        zhang.setName("张某");
        li = new Thread(officer);
        li.setName("李某");
        zhao = new Thread(officer);
        zhao.setName("赵某");
        zhang.start();
        li.start();
        zhao.start();
	}

}

编译运行

第一次运行

第二次运行

Exer3: 有一个关于Product类型的数组(货架),数组容量为16。生产者往货架上放置商品,消费者从货架上购买商品。二者是并发执行的。(货架空的时候只能生产,货架满的时候只能消费。)使用多线程并发机制,模拟商品编号从1到100的生产和消费过程。

要求:

只模拟一个生产者和一个消费者的情况;

package Exer3;

//销售
public class Customer implements Runnable{
	private Goods goods;
	int sl= 0;
	public Customer(Goods goods) {
		this.goods = goods;
	}
	@Override
	public void run() {
		while(true) {
			synchronized(goods) {
				if(goods.getGoodsNum()>0  && sl<100) {
					int saleNum = goods.saleGoods();//销售货物
					sl = sl + saleNum;    
					System.out.println("销售中......销售了"+saleNum+" 当前货物数量:"+goods.getGoodsNum()
					+ " 已销售" + sl );
				}	
			}
			//2次销售之间的时间随机生成,但不大于2s。
			try {
				int time = (int)(Math.random()*20+1);
				Thread.sleep(time);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

package Exer3;

//商品类
public class Goods {
	 int goodsNum = 0;//商品数目
	 int sc = 0;
	
	//进货,并返回进货数量
	public int addGoods() {
		int addNum = (int)(Math.random()*(16-goodsNum)+1);  //生产数量不大于货架容量16
		sc = sc +addNum;
		goodsNum +=addNum;
		if(sc>100) {
			sc -= addNum;
			goodsNum -= addNum;
			
			addNum = 100 - sc;
			goodsNum += addNum;
			sc += addNum;
		}
		return addNum;
	}
	//销售,并返回销售数量
	public int saleGoods() {
		int saleNum = (int)(Math.random()*this.goodsNum+1);//销售数量不大于商品数量
		goodsNum -= saleNum;
		return saleNum;
	}
	public int getGoodsNum() {
		return goodsNum;
	}
	public void setGoodsNum(int goodsNum) {
		this.goodsNum = goodsNum;
	}
	
}


package Exer3;


public class Producer implements Runnable{
	private Goods goods;
	
	public Producer(Goods goods) {
		this.goods = goods;
	}
	@Override
	public void run() {
		while(true) {
			synchronized(goods) {
				if(goods.getGoodsNum()<=0 && goods.sc<=100) {
					int addNum = goods.addGoods();//生产货物
					System.out.println("生产中......生产了"+addNum+" 当前货物数量为:"+goods.getGoodsNum()
					+" 已生产"+goods.sc);
					if (goods.sc == 100) {
						break;
					}
				}	
			}
		}
	}

}

package Exer3;

public class Exer3 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Goods goods = new Goods();  //销售和进货共用一个商品对象
		Thread t1 = new Thread(new Customer(goods));
		Thread t2 = new Thread(new Producer(goods));
		t1.start();
		t2.start();
	}

}


编译运行

生产中......生产了11 当前货物数量为:11 已生产11
销售中......销售了10 当前货物数量:1 已销售10
销售中......销售了1 当前货物数量:0 已销售11
生产中......生产了3 当前货物数量为:3 已生产14
销售中......销售了3 当前货物数量:0 已销售14
生产中......生产了3 当前货物数量为:3 已生产17
销售中......销售了2 当前货物数量:1 已销售16
销售中......销售了1 当前货物数量:0 已销售17
生产中......生产了7 当前货物数量为:7 已生产24
销售中......销售了4 当前货物数量:3 已销售21
销售中......销售了3 当前货物数量:0 已销售24
生产中......生产了2 当前货物数量为:2 已生产26
销售中......销售了1 当前货物数量:1 已销售25
销售中......销售了1 当前货物数量:0 已销售26
生产中......生产了16 当前货物数量为:16 已生产42
销售中......销售了6 当前货物数量:10 已销售32
销售中......销售了8 当前货物数量:2 已销售40
销售中......销售了2 当前货物数量:0 已销售42
生产中......生产了14 当前货物数量为:14 已生产56
销售中......销售了10 当前货物数量:4 已销售52
销售中......销售了1 当前货物数量:3 已销售53
销售中......销售了1 当前货物数量:2 已销售54
销售中......销售了1 当前货物数量:1 已销售55
销售中......销售了1 当前货物数量:0 已销售56
生产中......生产了14 当前货物数量为:14 已生产70
销售中......销售了3 当前货物数量:11 已销售59
销售中......销售了11 当前货物数量:0 已销售70
生产中......生产了10 当前货物数量为:10 已生产80
销售中......销售了7 当前货物数量:3 已销售77
销售中......销售了3 当前货物数量:0 已销售80
生产中......生产了15 当前货物数量为:15 已生产95
销售中......销售了13 当前货物数量:2 已销售93
销售中......销售了1 当前货物数量:1 已销售94
销售中......销售了1 当前货物数量:0 已销售95
生产中......生产了5 当前货物数量为:5 已生产100
销售中......销售了3 当前货物数量:2 已销售98
销售中......销售了2 当前货物数量:0 已销售100

集合框架

Exer4:LinkedListArrayList存放对象

  1. 利用面向对象的思想,创建以下类:
  1. Person类,包含Person的姓名和身份证号码,覆盖Object类的toString()方法,显示“姓名:XXX  身份证号:XXX”。
  2. Student类,继承Person类,包含学生的语文、数学、英文课的成绩,并覆盖父类的toString()方法,显示“姓名:XXX  身份证号:XXX 语文:XXX 数学:XXX 英文:XXX”。
  3. Teacher类,继承Person类,包含教师的工资。并覆盖父类的toString()方法,显示“姓名:XXX  身份证号:XXX 工资:XXX”
  1. 分别为以上三个类创建对象:

Person对象

Student对象

Teacher对象

姓名:张三

姓名:李四

姓名:王五

身份证号:12310001

身份证号:12320002

身份证号:12330003

语文: 89

工资:4000

数学: 93

英文: 94

  1. 将这三个对象存放在一个LinkedList或ArrayList对象中:

LinkedList<Person> list=new LinkedList<Person>();

ArrayList<Person> list=new ArrayList<Person>();

  1. 运行示例:   

  1. 练习使用LinkedList的其他方法。将自己的信息添加到链表的开头,以及结尾,然后再删除自己的信息。

返回类型

方法名称

描述

void

addFirst()

将指定元素插入此列表的开头

void

addLast()

将指定元素添加到此列表的结尾

E

removeFirst()

移除并返回此列表的第一个元素

E

removeLast()

移除并返回此列表的最后一个元素

boolean

add(Object o)

将指定的元素添加到列表中

package Exer4;

 class Person {
   String name;
   String ID;
   Person(String name,String ID){
	   this.name = name;
	   this.ID = ID;
   }
   public String toString() {
	   return "姓名:" + name + " 身份证号:" + ID;
   }
   
}
package Exer4;

public class Teacher extends Person{
    int wages;
    Teacher(String name,String ID,int wages){
    	super(name,ID);
    	this.wages = wages;
    }
    public String toString() {
    	return "姓名:" + name + " 身份证号:" + ID + " 工资:"+wages;
    }
}
package Exer4;

public class Student extends Person{
	int yuwen,shuxue,yingwen;
	Student(String name,String ID,int yuwen,int shuxue,int yingwen){
		super(name,ID);
		this.yuwen = yuwen;
		this.shuxue = shuxue;
		this.yingwen = yingwen;
	}
	public String toString() {
		return  "姓名:" + name + " 身份证号:" + ID+" 语文:"+yuwen
				+ " 数学:" + shuxue + " 英文:" + yingwen;
	}
}

 

package Exer4;
import java.util.*;


public class Exer4 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
        Person person = new Person("张三","12310001");
        Student student = new Student("李四","12320002",89,93,94);
        Teacher teacher = new Teacher("王五","12330003",4000);
        
        LinkedList<Person> list=new LinkedList<Person>();
        list.add(person);
        list.add(student);
        list.add(teacher);
        Person p1 = list.get(0);
        Person p2 = list.get(1);
        System.out.println(p1.toString());
        System.out.println(p2.toString());
        System.out.println();
        Person student1 = new Student("艾莎女王","11111111",100,100,100);
        list.addFirst(student1);  //将自己的信息添加到链表的开头
        list.addLast(student1);   //将自己的信息添加到链表的结尾
         p1 = list.getFirst();  
         p2 = list.getLast();
         
      
        for (int i =0;i<list.size();i++) {
        	Person pp = list.get(i);
        	System.out.println(pp.toString());
        }
       
       
        System.out.println();
        Person p3 = list.removeFirst();
        Person p4 = list.removeLast();
       Iterator<Person> iter = list.iterator();
    
       while(iter.hasNext()) {
    	   Person pp = iter.next();
    	   System.out.println(pp.toString());
       }
   
	}

}

编译运行

姓名:张三 身份证号:12310001
姓名:李四 身份证号:12320002 语文:89 数学:93 英文:94

姓名:艾莎女王 身份证号:11111111 语文:100 数学:100 英文:100
姓名:张三 身份证号:12310001
姓名:李四 身份证号:12320002 语文:89 数学:93 英文:94
姓名:王五 身份证号:12330003 工资:4000
姓名:艾莎女王 身份证号:11111111 语文:100 数学:100 英文:100

姓名:张三 身份证号:12310001
姓名:李四 身份证号:12320002 语文:89 数学:93 英文:94
姓名:王五 身份证号:12330003 工资:4000

Exer5:SET存放对象

  1. 将以下三个Person类的对象放在一个HashSet中,由于HashSet不能存放重复的元素(姓名和身份证号都不能重复),所以在Person类中,需要覆盖hashCode()方法和equals()方法。这里给出重写方法的程序:

   public boolean equals(Object obj) {

if (this == obj)

return true;

if (obj == null)

return false;

if (getClass() != obj.getClass())

return false;

Person other = (Person) obj;

if (name == null) {

if (other.name != null)

return false;

} else if (!name.equals(other.name))

return false;

if (id != other.id)

return false;

return true;

}

public int hashCode() {

final int prime = 31;

int result = 1;

result = prime * result + ((name == null) ? 0 : name.hashCode());

result = prime * result + id;

return result;

}

Person对象

Person对象

Person对象

姓名:张三

姓名:李四

姓名:王五

身份证号:12310001

身份证号:12320002

身份证号:12330003

再创建一个Person对象:

Person对象

姓名:王五

身份证号:12330003

能放入到刚才创建的HashSet中吗?通过这个对象来测试hashCode()方法和equals()方法的编写是否正确。

  1. 把集合中的元素打印出来(使用迭代器Iterator类)。
  2. 用TreeSet存放上面三个人,要求按照身份证号排序,打印出来。(注意使用TreeSet要实现Comparable接口,并覆盖compareTo()方法)
package Exer5;
import java.util.*;
 class Person implements Comparable {
     String name;
     int id;
     public Person(String name,int ID){
    	 this.name = name;
    	 id = ID; 
     }
     public boolean equals(Object obj) {
 		if (this == obj)
 			return true;
 		if (obj == null)
 			return false;
 		if (getClass() != obj.getClass())
 			return false;
 		Person other = (Person) obj;
 		if (name == null) {
 			if (other.name != null)
 				return false;
 		} else if (!name.equals(other.name))
 			return false;
 		if (id != other.id)
 			return false;
 		return true;
 	}	
 	public int hashCode() {
 		final int prime = 31;
 		int result = 1;
 		result = prime * result + ((name == null) ? 0 : name.hashCode());
 		
 		result = prime * result + id;
 		return result;
 	}
 	
 	public int compareTo(Object b) {
 		Person st = (Person)b;
 		return (this.id - st.id);
 	}
}
package Exer5;

import java.util.*;

public class Exer5 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Person p1 = new Person("张三",12310001);
		Person p2 = new Person("李四",12320002);
		Person p3 = new Person("王五",12330003);
	    HashSet<Person> sites = new HashSet<Person>();
	    boolean a = sites.add(p1);
	    boolean b = sites.add(p2);
	    boolean c = sites.add(p3);
	    System.out.println(a+" "+ b + " " +c);
	    
	    Person p4 = new Person("王五",12330003);
	   
	    System.out.println( sites.add(p4));  //如果添加成功,返回true,否则返回false
	    
	    
	    TreeSet<Person> mytree = new TreeSet<Person>();
	    mytree.add(p1);
	    mytree.add(p2);
	    mytree.add(p3);
	    Iterator<Person> te = mytree.iterator();
	    while(te.hasNext()) {
	    	Person per = te.next();
	    	System.out.println(per.name + " " +per.id);
	    }
	}

}

编译运行

true true true
false
张三 12310001
李四 12320002
王五 12330003

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值