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

201621123008 《Java程序设计》 第11周学习总结的更多相关文章

  1. 201521123045 <java程序设计>第11周学习总结

    201521123045 <java程序设计>第11周学习总结 1. 本周学习总结 2. 书面作业 2. 书面作业 Q1.1.互斥访问与同步访问完成题集4-4(互斥访问)与4-5(同步访问 ...

  2. 201521123027 <java程序设计>第11周学习总结

    1.本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 2.书面作业 1.互斥访问与同步访问 完成题集4-4(互斥访问)与4-5(同步访问) 1.1 除了使用synchro ...

  3. 2018面向对象程序设计(Java)第11周学习指导及要求

    2018面向对象程序设计(Java)第11周学习指导及要求 (2018.11.8-2018.11.11)   学习目标 (1) 掌握Vetor.Stack.Hashtable三个类的用途及常用API: ...

  4. 面向对象程序设计(JAVA) 第11周学习指导及要求

    2019面向对象程序设计(Java)第11周学习指导及要求 (2019.11.8-2018.11.11)   学习目标 理解泛型概念: 掌握泛型类的定义与使用: 掌握泛型方法的声明与使用: 掌握泛型接 ...

  5. 20145236 《Java程序设计》第九周学习总结

    20145236 <Java程序设计>第九周学习总结 教材学习内容总结 第十六章 整合数据库 JDBC简介 1.JDBC是java联机数据库的标准规范.它定义了一组标准类与接口,标准API ...

  6. 2018-2019 2 20175230《Java程序设计》第九周学习总结

    <Java程序设计>第九周学习总结 主要内容 MySQL数据库管理系统 1.下载 2.安装 启动MySQL数据库服务器 1.启动 2.root用户 MySQL客户端管理工具 建立连接 建立 ...

  7. 20175209 《Java程序设计》第九周学习总结

    20175209 <Java程序设计>第九周学习总结 一.教材知识点总结 有关数据库下载中存在可能出现的问题已经在博客<数据库安装和使用过程中出现的一些问题>给出了相应的解决办 ...

  8. 20175208 《Java程序设计》第九周学习总结

    20175208 2018-2019-2 <Java程序设计>第九周学习总结 一.教材学习内容总结: 第11章 JDBC与MySQL数据库 MySQL数据库管理系统 MySQL数据库管理系 ...

  9. 20175202 《Java程序设计》第九周学习总结

    20175202 2018-2019-2 <Java程序设计>第九周学习总结 教材知识点总结 第11章 JDBC与MySQL数据库 MySQL数据库管理系统 MySQL数据库管理系统,简称 ...

  10. 20175227张雪莹 2018-2019-2 《Java程序设计》第九周学习总结

    20175227张雪莹 2018-2019-2 <Java程序设计>第九周学习总结 教材学习内容总结 第十一章 JDBC数据库操作 MySQL数据库管理系统 下载安装MySQL 若下载的是 ...

随机推荐

  1. base64 压缩图片

    //图片处理 afterimg(err, photos) { var _this = this; if(err && err != null && err != '') ...

  2. jq控制select值为某个时选中

    $("#selectche_type option").each(function(){//用id ,用class好像不得,不知道为何 alert(2) if($(this).va ...

  3. 物料没加DUMMY

    会加入DUMMY的表 IN_ITEM,IN_ITEM_SITE,IN_SALES_ORDER 加入DUMMY的存储过程名为SAP_MATERIAL_SO. FP_CHANGE_MO_ROUTING的第 ...

  4. javascript学习笔记(一):基础、输出、注释、引用、变量、数据类型

    javascript脚本必须位于<script></script>之间,<script>标签可以位于<head>中,也可以位于<body>中 ...

  5. 解题7(FindFirstOnlyOne)

    题目描述 找出字符串中第一个只出现一次的字符 输入描述: 输入一个非空字符串 输出描述: 输出第一个只出现一次的字符,如果不存在输出-1 示例1 输入 asdfasdfo 输出 o 代码如下: pac ...

  6. python3 文件读写,编码错误UnicodeDecodeError

    问题:python3 with open文件进行读写,报编码错误 /usr/local/Cellar/python3/3.5.2/Frameworks/Python.framework/Version ...

  7. [Android] TextView长按复制实现方法小结(转载)

    这是别人写的,既然别人总结过了,那我就不花时间研究这个了,但往后会补充一些使用经验之类的 原文地址:http://blog.csdn.net/stzy00/article/details/414778 ...

  8. DataGridView中DataGridViewComboBoxColumn的一些相关应用(一)让其值改变时触发事件-转

    转自  https://maodaili.de/mao.php?u=a%2FMrbEvUE8PnCuc7FrhJi0Rqd3kmOBHPZUbcJ1c2hbJUK0RYWpAf4lhIOddItP%2 ...

  9. 【centos】centos安装配置samba

    因为我的centos为一台阿里云服务器,想和我本机(mac)进行文件共享.所以在我的阿里云上安装配置samba. 服务器环境:centos 7.3 本地环境:mac 第1步:首先查看是否已经安装过了s ...

  10. java发送http连接

    原生方式:@转载文章 import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamRead ...