zoukankan      html  css  js  c++  java
  • 201621123008 《Java程序设计》 第11周学习总结

    1. 本周学习总结

    1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容。

    2. 书面作业

    本次PTA作业题集多线程

    1. 源代码阅读:多线程程序BounceThread

    1.1 BallRunnable类有什么用?为什么代码中需要调用Thread.sleep进行休眠?

    分析: BallRunnable类实现了Runnable接口,其run方法包含线程执行体,该方法根据STEPS的值来控制绘制小球的次数,通过move方法来确定小球的位置。而使用sleep让线程进入阻塞状态,即,小球暂时停留,让人得以观察其运动轨迹。

    1.2 Ball.java只做了两件事,这两件事分别是什么?BallComponent对象是干什么的?其内部的ArrayList有什么用?程序运行过程中,生成了几个BallComponent对象?该程序使用了多线程技术,每个小球是分别在不同的线程中进行绘制吗?

    分析:

    • Ball.java:该类有两个方法:

    • public void move(Rectangle2D bounds):重绘小球时确定其位置。

    • public Ellipse2D getShape():得到一个Ellipse2D.Double对象,存储2D圆对象。

    • BallComponent对象:

    • 加小球,画小球

    • ArrayList用于存放加入的小球

    • 生成了一个BallComponent对象

    • 每点击一次start按钮就产生一个线程。每个小球在自己所属线程内进行绘制

    1.3 选做:程序改写:程序运行时,每个小球都是从固定位置出发。如何改写该程序,使得当点击start时,每个小球可以从不同位置出发、以不同的步进移动?

    Ball中的move方法进行修改。

        x=Math.random()*bounds.getMaxX();
         y=Math.random()*bounds.getMaxY();
         dx=Math.random()*5;
         dy=Math.random()*5;
    

    1.4 选做:不同小球的移动轨迹一模一样。改造程序,使得每个小球运行轨迹不完全一样,比如有的可以走余弦轨迹、有的可以走方波轨迹、有的走布朗运动、有的走五角星,等等。

    2. 实验总结:题集(多线程)

    2.1 题目:Thread、PrintTask、Runnable与匿名内部类。并回答:a)通过定义Runnable接口的实现类来实现多线程程序比通过继承自Thread类实现多线程程序有何好处?b) 6-1,6-3,6-11实验总结。

    分析:若我们创建的类继承自Thread那么该类就是一个Thread,若我们通过实现Runnable接口,则我们创建的类还可以再继承自其他类,总的来说操作Runnable接口的好处就是比较有弹性。

    总结:

    6-1:通过继承Thread并重写run方法来创建线程,Thread本身就实现了Runnable接口

    6-3:使用Thread.currentThread()获得当前执行线程对象,从而获得线程名

    6-11:通过实现Runnable接口,并重写run方法来创建线程。

    2.2 使用Lambda表达式改写6-3

      Thread t1 = new Thread(()-> {
          
            		System.out.println(mainThreadName);
            		System.out.println(Thread.currentThread().getName());
            		System.out.println(Arrays.toString(Thread.class.getInterfaces()));
            	
            });
    

    2.3 题目:6-2(Runnable与停止线程)。回答:需要怎样才能正确地停止一个运行中的线程?

    runcall方法执行完后线程正常死亡,由于stop方法易产生错误,故可以在runcall方法中依据标志位进行循环控制实现线程的停止。

    2.4 选做:6-8(CountDownLatch)实验总结

    总结:

    • CountDownLatch:一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行。CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。

    • ExecutorService:提交任务,并进行调度执行。通过 Executors 类来创建的线程池的类型:拥有固定线程数的线程池,如果没有任务执行,那么线程会一直等待, Executors.newFixedThreadPool()

    2.5 选做:6-9(集合同步问题)实验总结

    总结: 使用Collections.synchronizedList(new ArrayList<Integer>());将传入的操作对象打包,返回线程安全的对象

    2.6 选做:较难:6-10(Callable),并回答为什么有Runnable了还需要Callable?实验总结。

    总结: 其实CallableRunnable都是将方法包装成线程执行体,区别就是Callable中的call方法具有返回值,可以声明抛出异常对象。正是利用这个性质我们可以通过call方法返回n对应的斐波那契值,关联Fututr得到返回值,继而计算斐波那契数列的前n项和。

    3. 互斥访问

    3.1 修改TestUnSynchronizedThread.java源代码使其可以同步访问。(关键代码截图,需出现学号)

    Counter类中的方法进行了修改
    修改后的代码

    class Counter {
    	private volatile static int id = 0;
    
    	public synchronized static void addId() {
    		id++;
    	}
    
    	public synchronized static void subtractId() {
    		id--;
    	}
    
    	public static int getId() {
    		return id;
    	}
    }
    

    运行结果

    3.2 选做:进一步使用执行器改进相应代码(关键代码截图,需出现学号)

    参考资料:Java多线程之Executor、ExecutorService、Executors、Callable、Future与FutureTask

    /**
     * 
     * @author 周文华
     *
     */
    public class TestUnSynchronizedThread {
    
    	public static void main(String[] args) throws InterruptedException {
    
    		List<Callable<Integer>> taskList = new ArrayList<>();
    		ExecutorService exec = Executors.newSingleThreadScheduledExecutor();
    		for (int i = 0; i < 6; i++) {
    			if (i < 3)
    				taskList.add(new Adder());
    			else
    				taskList.add(new Subtracter());
    		}
    		List<Future<Integer>>list=exec.invokeAll(taskList);
    		exec.shutdown();
    		try {
    			System.out.println(list.get(list.size()-1).get());
    		} catch (ExecutionException e) {
    			e.printStackTrace();
    		}
    		System.out.println("main end");
    	}
    }
    
    class Adder implements Callable<Integer> {
    
    	@Override
    	public Integer call() {
    		for (int i = 0; i < 10000; i++)
    			Counter.addId();
    		System.out.println(Thread.currentThread().getName() + " end");
    		return Counter.getId();
    	}
    }
    
    class Subtracter implements Callable<Integer> {
    
    	@Override
    	public Integer call() {
    		for (int i = 0; i < 10000; i++)
    			Counter.subtractId();
    		System.out.println(Thread.currentThread().getName() + " end");
    		return Counter.getId();
    	}
    }
    
    class Counter {
    	private volatile static int id = 0;
    
    	public synchronized static void addId() {
    		id++;
    	}
    
    	public synchronized static void subtractId() {
    		id--;
    	}
    
    	public static int getId() {
    		return id;
    	}
    }
    

    运行结果

    4. 互斥访问与同步访问

    完成题集6-4(互斥访问)与6-5(同步访问)

    4.1 除了使用synchronized修饰方法实现互斥同步访问,还有什么办法可以使用synchronized实现互斥同步访问,使用代码说明(请出现相关代码及学号)?

    分析:还可以通过同步代码块实现互斥访问

    代码:

    package Test02;
    
    import javax.swing.plaf.SliderUI;
    
    public class SynchronizedTest {
    
        //锁定方法,加锁对象SynchronizedTest实例
    	public synchronized void method1() {
    		System.out.println("method 1 ...");
    		try {
    			Thread.sleep(5000);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    
        //锁定SynchronizedTest对象
    	public void method2() {
    		synchronized (this) {
    			System.out.println("method 2 ...");
    		}
    	}
    
        //方法内部进行锁定,锁定对象为str
    	public void method3() {
    		String str = "mehtod 3 ...";
    		synchronized (str) {
    			System.out.println(str);
    
    		}
    	}
    
    	public static void main(String[] args) {
    		SynchronizedTest test = new SynchronizedTest();
    		Thread th1 = new Thread(new Runnable() {
    
    			@Override
    			public void run() {
    				test.method1();
    
    			}
    		});
    		Thread th2 = new Thread(new Runnable() {
    
    			@Override
    			public void run() {
    				test.method2();
    
    			}
    		});
    
    		Thread th3 = new Thread(new Runnable() {
    
    			@Override
    			public void run() {
    				test.method3();
    
    			}
    		});
    		th1.start();
    		th2.start();
    		th3.start();
    	}
    }
    
    

    4.2 同步代码块与同步方法有何区别?

    分析:由上例三个method可以看出使用同步代码块可以更实现精细的锁定,我们可以锁定只会发生竞速状况的区块。

    4.3 实现互斥访问的原理是什么?请使用对象锁概念并结合相应的代码块进行说明。当程序执行synchronized同步代码块或者同步方法时,线程的状态是怎么变化的?

    分析:我们知道在线程是并发进行的,即在同一时刻只能有一条指令执行,但多个线程指令快速轮换执行,CPU执行速度很快,使得在宏观上有同时执行的效果。线程同步最经典的例子是存取取钱的问题,若采用并发线程,进行取钱操作,很可能由于线程调度的不确定性,使的取出的钱数大于账户余额,这时我们就需要一个同步监视器了,在我们进行取钱操作之前得先获得同步监视器的锁定,即获得一个共有资源的使用权,使用期间其他线程无法对该资源进行操作,使用完之后再把锁交出,让其他线程去竞争使用权,从而保证了线程安全性。

    4.4 Java多线程中使用什么关键字实现线程之间的通信,进而实现线程的协同工作?

    分析:可以使用Object类的wait(),notify(),notifyAll(),但是这些方法必须由同步监视器对象来调用。

    wait():导致当前线程等待,直到其他线程调用该同步监视器的notify(),notifyAll()方法。

    notify():唤醒在此同步监视器上等待的单个线程,注意,只有在当前线程放弃了同步监测器的锁定之后(使用wait()方法后),才可以执行被唤醒的线程,选择随意。

    notifyAll():唤醒所有在此监视器上等待的线程其他与notify()类似。

    5. 线程间的合作:生产者消费者问题

    5.1 运行MyProducerConsumerTest.java。正常运行结果应该是仓库还剩0个货物。多运行几次,观察结果,并回答:结果正常吗?哪里不正常?为什么?

    分析:分析代码可知,该程序功能是放入先100个货物再取出100个货物,结果应当为0,执行几次后发现结果并不是正确的,应为仓库的容量为10,当仓库满时就应该停止添加操作,唤醒取出操作,而程序没有做这些操作,只是一个线程只负责添加,一个线程只负责取出,两线程之间没有实现通信。

    5.2 使用synchronized, wait, notify解决该问题(关键代码截图,需出现学号)

    public synchronized void add(String t) {
    		if (repo.size() >= capacity) {
    			System.out.println("仓库已满!无法添加货物。");
    			try {
    				wait();
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		} else {
    			repo.add(t);
    			notify();
    		}
    		
    	}
    	public synchronized void remove() {
    		if (repo.size() <= 0) {
    			System.out.println("仓库无货!无法从仓库取货");
    			try {
    				wait();
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		} else {
    			repo.remove(0);
    			notify();
    		}
    	}
    

    5.3 选做:使用Lock与Condition对象解决该问题。

    class Repository {// 存放字符串的仓库
    	private int capacity = 10;// 仓库容量默认为10
    	private List<String> repo = new ArrayList<String>();// repo(仓库),最多只能放10个
    	Lock lock = new ReentrantLock();
    	Condition condition = lock.newCondition();
    
    	public void add(String t) {
    		try {
    			lock.lock();
    			while(repo.size() >= capacity) {
    					try {
    						condition.await();
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    			} 
    				repo.add(t);
    				condition.signal();
    		
    		} finally {
    			lock.unlock();}
    	}
    
    	public void remove() {
    		try {
    			lock.lock();
    			while (repo.size() <= 0) {
    				try {
    					condition.await();
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			} 
    				repo.remove(0);
    				condition.signal();
    			
    		} finally {
    			lock.unlock();
    		}
    	}
    
    	public int size() {
    		try {
    			lock.lock();
    			return repo.size();
    		} finally {
    			lock.unlock();
    		}
    	}
    }
    

    6. 面向对象设计作业-图书馆管理系统

    6.1 系统的功能模块表格,表格中体现出每个模块的负责人。

    6.2 运行视频

    6.3 讲解自己负责的模块,并粘贴自己负责模块的关键代码(出现学号及姓名)。

    系统的基本类及类图

    给出关键类截图
    代码写的很烂,改进中,希望大家给我一些建议。

    public class Entry {
    	/**
    	 * 职业选择,返回对应的实例变量。
    	 * 
    	 * @param profession
    	 * @return
    	 */
    	public static User professionJudge(String profession) {
    		if (profession.equalsIgnoreCase("Administrator")) {
    			Administrator administrator = new Administrator();
    			administrator.setAdmit(true);
    			return administrator;
    		}
    		if (profession.equalsIgnoreCase("Student"))
    			return new Student();
    		if (profession.equalsIgnoreCase("Teacher"))
    			return new Teacher();
    		else
    			return null;
    
    	}
    
    	/**
    	 * 填写注册前的基本信息。 返回一个user
    	 * 
    	 * @param userNo
    	 * @param name
    	 * @param userId
    	 * @param password
    	 * @return
    	 */
    	public static <T extends User> T writePersonalInformation(String profession, Long userNo, String name,
    			String userId, String password) {
    		User user = professionJudge(profession);
    		if (user != null) {
    			LoginInformation info = new LoginInformation();
    			info.setId(userId);
    			info.setPassword(password);
    			user.setUserNo(userNo);
    			user.setUserName(name);
    			user.setLoginInformation(info);
    			user.setLibraly(new Library());
    			return (T) user;
    		}
    		return null;
    
    	}
    
    	/**
    	 * 将user加入users 只是先将user加入到user仓库
    	 * 
    	 * @param user
    	 * @param set
    	 * @return
    	 */
    	public static <T extends User> boolean register(User user, UserStorage storage) {
    		boolean flag = false;
    		ObjectInputStream input = null;
    		ObjectOutputStream output = null;
    		if (user != null) {
    			// 先判断user仓库是否有user信息,若没有则去文件中查找
    			if (storage.isExit(user.getLoginInformation().getId()) == null) {
    				try {
    					// 打开文件成功,说明文件存在,不注册
    					input = new ObjectInputStream(
    							new BufferedInputStream(new FileInputStream(user.getLoginInformation().getId())));
    				} catch (FileNotFoundException e) {
    					// 打文件开不成功,说明文件不存在那就注册。
    					storage.addUser(user);
    					flag = true;
    					/*
    					 * try { output = new ObjectOutputStream( new BufferedOutputStream(new
    					 * FileOutputStream(user.getLoginInformation().getId())));
    					 * output.writeObject(user); System.out.println("已经注册"); flag = true; } catch
    					 * (FileNotFoundException e1) { e1.printStackTrace(); } catch (IOException e1) {
    					 * e1.printStackTrace(); } finally { try { output.close(); } catch (IOException
    					 * e1) { e1.printStackTrace(); } }
    					 */
    				} catch (IOException e) {
    					e.printStackTrace();
    				} finally {
    					try {
    						if (input != null)
    							input.close();
    					} catch (IOException e) {
    						e.printStackTrace();
    					}
    				}
    			}
    		}
    		return flag;
    
    		/*
    		 * boolean result = storage.isExit(user.getLoginInformation().getId()); if
    		 * (result) { return false; } else { storage.addUser(user); return true; }
    		 */
    
    	}
    
    	/**
    	 * 登录 直接从文件读取内容
    	 * 
    	 * @param name
    	 * @param password
    	 * @param users
    	 * @return
    	 */
    
    	public static int login(String userId, String password, UserStorage users) {
    		ObjectInputStream input = null;
    		User user = null;
    		int flag = 0;
    		if (users.isExit(userId) == null) {
    			try {
    				input = new ObjectInputStream(new BufferedInputStream(new FileInputStream(userId)));
    				try {
    					user = (User) input.readObject();
    					if (user.getLoginInformation().getPassword().equals(password)) {
    						// 登录成功,將user加入Users最后退出系统时自动写入文件
    						users.addUser(user);
    						flag = 1;
    					} else {
    						// 帐号密码不匹配
    						flag = 0;
    					}
    				} catch (ClassNotFoundException e) {
    					e.printStackTrace();
    				}
    
    			} catch (FileNotFoundException e) {
    				// 该帐号没有注册
    				flag = -1;
    			} catch (IOException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			} finally {
    				try {
    					if (input != null)
    						input.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    		} else {
    			user = users.isExit(userId);
    			if (password.equals(user.getLoginInformation().getPassword())) {
    				flag = 1;
    			} else {
    				flag = 0;
    			}
    		}
    		return flag;
    
    	}
    
    	/*
    	 * boolean result = users.isExit(name); if (result) { int flag = 0;
    	 * Iterator<User> iterator = users.getUserSet().iterator(); while
    	 * (iterator.hasNext()) { if
    	 * (password.equals(iterator.next().getLoginInformation().getPassword())) flag =
    	 * 1; // 登录成功 else flag = 0; // 帐号密码不匹配 } return flag;
    	 * 
    	 * } else { return -1; // 帐号不存在
    	 * 
    	 * }
    	 * 
    	 * }
    	 */
    	/**
    	 * 程序开始时恢复书库信息
    	 * 
    	 * @return
    	 */
    	public static StackRoom restoreStackRoom() {
    		StackRoom stackRoom = null;
    		try {
    			ObjectInputStream input = new ObjectInputStream(new BufferedInputStream(new FileInputStream("StackRoom")));
    			try {
    				stackRoom = (StackRoom) input.readObject();
    			} catch (ClassNotFoundException e) {
    				e.printStackTrace();
    			}
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    		;
    		return stackRoom;
    
    	}
    /**
     * 程序结束时使用,更新书库信息
     * 由于用户借书,管理员添加,删除书造成书本数量上的变化
     * @param stackRoom
     */
    	public static void saveOrUpdateStackRoom(StackRoom stackRoom) {
    		ObjectOutputStream output = null;
    		try {
    			output = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("StackRoom")));
    			output.writeObject(stackRoom);
    		} catch (FileNotFoundException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		} finally {
    			if (output != null) {
    				try {
    					output.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    
    	}
    }
    
    public class Library implements Universal, Serializable {
    	private Map<String, BookItem> libraryMap = new TreeMap<>();
    
    	public <T> void print(Collection<T> value) {
    		Iterator iterator = value.iterator();
    		while (iterator.hasNext())
    			System.out.println(iterator.next());
    
    	}
    
    	public void showBooks() {
    		Collection<BookItem> BooksItems = libraryMap.values();
    		Iterator<BookItem> iterator = BooksItems.iterator();
    		while (iterator.hasNext()) {
    			System.out.println(iterator.next());
    			;
    		}
    	}
    
    	private boolean isExit(String bookId) {
    		return libraryMap.containsKey(bookId);
    	}
    
    	/**
    	 * 借书,借书成功书库中该书数量减一
    	 * 
    	 * @param bookId
    	 * @param stackRoom
    	 * @return
    	 */
    	public int borrowBooks(String bookId, StackRoom stackRoom) {
    		Collection<Set<BookItem>> setBooksItems = stackRoom.getBooksMap().values();
    		Iterator<Set<BookItem>> iterator = setBooksItems.iterator();
    		while (iterator.hasNext()) {
    			Set<BookItem> setBookItem = iterator.next();
    			Iterator setBooks = setBookItem.iterator();
    			while (setBooks.hasNext()) {
    				BookItem bookItem = (BookItem) setBooks.next();
    				Book book = bookItem.getBook();
    				if (book.getBookId().equals(bookId)) {
    					boolean result = isExit(bookId);
    					if (result) {
    
    						BookItem a = libraryMap.get(bookId);
    						System.out.println(a);
    						if (a.getCount() >= bookItem.getCount()) {
    							return 0; // 该书以及全部借出
    						} else {
    							a.setCount(a.getCount() + 1);
    							// 书库的书数量减一
    							bookItem.setCount(bookItem.getCount() - 1);
    							return 1; // 借书成功
    						}
    					} else {
    						libraryMap.put(bookId, new BookItem(book, 1));
    						return 1;
    					}
    				}
    			}
    
    		}
    		return -1; // bookId有误,不存在该书
    
    	}
    
    	/**
    	 * 还书,还书成功书库中该书数量加一
    	 * 
    	 * @param bookId
    	 * @return
    	 */
    	public boolean returningBooks(String bookId, StackRoom stackRoom) {
    		if (libraryMap.containsKey(bookId)) {
    			String category = libraryMap.get(bookId).getBook().getCategory();
    			libraryMap.remove(bookId);
    			Set<BookItem> bookItems = stackRoom.getBooksMap().get(category);
    			for (BookItem bookItem : bookItems) {
    				if (bookItem.getBook().getBookId().equals(bookId)) {
    					bookItem.setCount(bookItem.getCount() + 1);
    					break;
    				}
    			}
    			return true;
    		} else {
    			return false;
    		}
    
    	}
    
    }
    
    public class StackRoom implements Serializable{
    
    	private  Map<String, Set<BookItem>> booksMap = new HashMap<>();
    
    	//已经填入数据,该方法废弃
    	/*static {
    
    		Set<BookItem> economicalBook = new HashSet<>();
    		economicalBook.add(new BookItem(
    				new EconomicalBook("001", "货币金融学", "弗雷德克里S·米什金", "经济", new GregorianCalendar(2001, 6, 1)), 5));
    		economicalBook.add(
    				new BookItem(new EconomicalBook("002", "博弈论与信息学", "	张维迎", "经济", new GregorianCalendar(2001, 6, 1)), 5));
    		economicalBook.add(
    				new BookItem(new EconomicalBook("003", "国富论", "亚当.斯密", "经济", new GregorianCalendar(2001, 6, 1)), 5));
    		economicalBook.add(new BookItem(
    				new EconomicalBook("004", "牛奶可乐经济学", "弗雷德克里S·米什金", "经济", new GregorianCalendar(2001, 6, 1)), 5));
    		booksMap.put("经济", economicalBook);
    
    		Set<BookItem> militaryBook = new HashSet<>();
    		militaryBook
    				.add(new BookItem(new MilitaryBook("005", "孙子兵法", "孙子", "军事", new GregorianCalendar(2001, 6, 1)), 5));
    		militaryBook.add(new BookItem(
    				new MilitaryBook("006", "第二次世界大战史", "马丁·吉尔伯特 ", "军事", new GregorianCalendar(2001, 6, 1)), 5));
    		militaryBook
    				.add(new BookItem(new MilitaryBook("007", "太平洋战争", "青梅煮雨", "军事", new GregorianCalendar(2001, 6, 1)), 5));
    		militaryBook
    				.add(new BookItem(new MilitaryBook("0010", "梦残干戈", "黄朴民", "军事", new GregorianCalendar(2001, 6, 1)), 5));
    		booksMap.put("军事", militaryBook);
    
    	}*/
    	
    	
    
    	/**
    	 * 打印
    	 * 
    	 * @param value
    	 */
    	public <T> void print(Collection<T> value) {
    		if (value == null)
    			System.out.println("图书馆无该种类书籍相关信息");
    		else {
    			Iterator iterator = value.iterator();
    			while (iterator.hasNext())
    				System.out.println(iterator.next());
    		}
    
    	}
    
    	public Map<String, Set<BookItem>> getBooksMap() {
    		return booksMap;
    	}
    
    	public void setBooksMap(Map<String, Set<BookItem>> booksMap) {
    		this.booksMap = booksMap;
    	}
    
    	/**
    	 * 展示书库,配合搜索使用
    	 */
    	public void showBooks() {
    		Collection<Set<BookItem>> bookItemSet = booksMap.values();
    		Iterator<Set<BookItem>> iteratorSet = bookItemSet.iterator();
    		while (iteratorSet.hasNext()) {
    			print(iteratorSet.next());
    		}
    	}
    
    	/**
    	 * 搜索:依据书的类别
    	 * 返回Set,使用print()进行打印
    	 * @param key
    	 * @return
    	 */
    	public Set<BookItem> searchBooks(String key) {
    		Set<BookItem> bookItems = booksMap.get(key);
    		return bookItems;
    	}
    	
    
    }
    

    7. 选做:使用其他方法解决题目5的生产者消费者问题。

    相关资料:来自百度

    7.1 使用BlockingQueue解决生产者消费者问题关键代码截图

    关键代码

    class Repository {// 存放字符串的仓库
    	BlockingQueue repo = new LinkedBlockingQueue(10);
    	
    	public  void add(String t) {
    			try {
    				repo.put(t);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    	}
    	public  void remove() {
    	try {
    		repo.take();
    	} catch (InterruptedException e) {
    		e.printStackTrace();
    	}
    	}
    	public int size(){
    		return repo.size();
    	}
    }
    

    7.2 说明为什么不需要显示的使用wait、notify就可以解决同步问题。这样解决相比较wait、notify有什么优点吗?

    分析: BlockingQueue顾名思义,阻塞队列。当队列满了的时候进行出队列操作,当队列空了的时候进行入队列操作,我们可以设置阻塞队列的容量,入队操作采用put()方法时,若队列已满则调用此方法的线程被阻断,直到有空间再继续,出队操作采用take()方法时,若队列为空,则阻断进入等待状态直到队列有新的对象被加入为止。

    优点:就是我们可以坐享其成,虽然API很强大,但我们也要了解其原理,不能当只会查API的程序员。

    7.3 使用Condition解决生产者、消费者问题。

    class Repository {// 存放字符串的仓库
    	private int capacity = 10;// 仓库容量默认为10
    	private List<String> repo = new ArrayList<String>();// repo(仓库),最多只能放10个
    	Lock lock = new ReentrantLock();
    	Condition condition = lock.newCondition();
    
    	public void add(String t) {
    		try {
    			lock.lock();
    			while(repo.size() >= capacity) {
    					try {
    						condition.await();
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    			} 
    				repo.add(t);
    				condition.signal();
    		
    		} finally {
    			lock.unlock();}
    	}
    
    	public void remove() {
    		try {
    			lock.lock();
    			while (repo.size() <= 0) {
    				try {
    					condition.await();
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			} 
    				repo.remove(0);
    				condition.signal();
    			
    		} finally {
    			lock.unlock();
    		}
    	}
    
    	public int size() {
    		try {
    			lock.lock();
    			return repo.size();
    		} finally {
    			lock.unlock();
    		}
    	}
    }
    

    8. 选做:编写一段代码,证明你会使用ForkJoinPool.

    3.码云及PTA

    题目集:多线程

    3.1. 码云代码提交记录

    • 在码云的项目中,依次选择“统计-Commits历史-设置时间段”, 然后搜索并截图
      必须出现几个要素:提交日期-用户名(姓名与学号)-不提交说明

    3.2 截图"多线程"PTA提交列表

    • 需要有两张图(1. 排名图。2.PTA提交列表图)



    3.3 统计本周完成的代码量

    • 需要将每周的代码统计情况融合到一张表中

    周次 总代码量 新增文件代码量 总文件数 新增文件数
    1 665 20 20 20
    2 1705 23 23 23
    3 1834 30 30 30
    4 1073 1073 17 17
    5 1073 1073 17 17
    6 2207 1134 44 27
    7 3292 1085 59 15
    8 3505 213 62 3
    9 8043 1246 153 16
    10 8606 543 167 14
    11 9203 597 191 24
    12 9203 0 191 0
  • 相关阅读:
    C++ Operate FTP
    md /mdd /ml /mt/mtd
    从MySpace基于.NET平台的六次重构经历,来感受分布式系统。
    分布式缓存BeIT Memcached简介
    Asp.Net应用程序中为什么要MachineKey?如何生成MachineKey?
    马云飞机上写长贴:再一次和新同事们谈谈看法
    memcached完全剖析
    ESET ESS/EAV 5 正式版 中英文32/64位 (注册版) 下载
    Windows下的.NET+ Memcached安装
    在 ASP.NET 環境下使用 Memcached 快速上手指南
  • 原文地址:https://www.cnblogs.com/Dzwh/p/7977740.html
Copyright © 2011-2022 走看看