Skip to content

Commit 000e391

Browse files
committed
Updated 'src/Ch15_Networking_and_Threads_Make_a_Connection.md'
1 parent 9ae41ef commit 000e391

1 file changed

Lines changed: 42 additions & 44 deletions

File tree

src/Ch15_Networking_and_Threads_Make_a_Connection.md

Lines changed: 42 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ Socket chatSocket = new Socket("196.164.1.103", 5000);
234234
// InputStreamReader 是底层字节流(就比如这里的从套接字获取
235235
// 到的那个),与高级别字符流(如同后面那个作为链式流顶部的
236236
// `BufferedReader`)之间的“桥梁”
237-
//
237+
//
238238
// 这里只须从该套接字请求一个输入流即可!所获取到的,就是
239239
// 一个低级别的连接性流,不过这里只要将其链接到某个对文本
240240
// 更加友好的东西上(All we have to do is ASK the socket for
@@ -327,8 +327,7 @@ Socket chatSocket = new Socket("196.164.1.103", 5000);
327327

328328
你还等什么呢,若没有这个 app,没人知道你会失去些什么机会。
329329

330-
1**连接**
331-
330+
1. **连接**
332331

333332
**Connect**
334333

@@ -339,8 +338,7 @@ Socket chatSocket = new Socket("196.164.1.103", 5000);
339338
*19 - `AdviceGuy` app 建立连接*
340339

341340

342-
2) **读取**
343-
341+
2. **读取**
344342

345343
**Read**
346344

@@ -473,11 +471,11 @@ import java.net.*;
473471
public class DailyAdviceServer {
474472
// 日常劝解来自这个数组
475473
// (请记住,这些字符串是由编码编辑器包装起来的单词。绝不要在字符串
476-
// 中间敲入回车(remember, these Strings were word-wrapped by
474+
// 中间敲入回车(remember, these Strings were word-wrapped by
477475
// the code editor. Never hit return in the middle of a String)!)
478476
String[] adviceList = {
479-
"少食多餐",
480-
"买些紧身牛仔裤。他们不会让你看起来显胖。",
477+
"少食多餐",
478+
"买些紧身牛仔裤。他们不会让你看起来显胖。",
481479
"一个字:不合适",
482480
"就今天而言,要诚实,告诉你的老板你的真实想法。",
483481
"对于这个发型,你应该三思而后行"
@@ -498,7 +496,7 @@ public class DailyAdviceServer {
498496
// 客户端通信的 `Socket`(在某个匿名端口)
499497
//
500498
// the accept method blocks (just sits there) until
501-
// a request comes in, and then the method returns
499+
// a request comes in, and then the method returns
502500
// a Socket(on some anonymous port) for communicating
503501
// with the client
504502
Socket sock = serverSock.accept();
@@ -507,7 +505,7 @@ public class DailyAdviceServer {
507505
// PrintWriter,并把一个字符串的劝解消息,发送给他(println())
508506
// 而由于完成了这个客户端的请求,所以随后就要关闭这个套接字。
509507
//
510-
// now we use the Socket connection to the client to make a
508+
// now we use the Socket connection to the client to make a
511509
// PrintWriter and send it (println()) a String advice message
512510
// Then we close the Socket because we're done with this client.
513511
//
@@ -695,9 +693,9 @@ public class SimpleChatClientA extends JFrame {
695693
try {
696694
// 由于用的是 localhost ,因此可以在一台机器上测试客户端
697695
// 和服务器。
698-
//
699-
// 这里就是构造 Socket 与 PrintWriter (这个 setUpNetworking()
700-
// 方法,是在刚刚显示出该 app 的 GUI 界面后,从类 SimpleChatClientA
696+
//
697+
// 这里就是构造 Socket 与 PrintWriter (这个 setUpNetworking()
698+
// 方法,是在刚刚显示出该 app 的 GUI 界面后,从类 SimpleChatClientA
701699
// 构造器调用)。
702700
sock = new Socket("127.0.0.1", 5000);
703701
writer = new PrintWriter(new OutputStreamWriter(sock.getOutputStream(), "UTF-8"));
@@ -920,7 +918,7 @@ Java 中的多线程技术,意味着这里必须同时要了解 *线程* 及
920918
// 这里的是否像这样输入代码无关。)
921919
//
922920
// The Runnable interface defines only one method,
923-
// public void run(). (Remember, it's an interface so the
921+
// public void run(). (Remember, it's an interface so the
924922
// method is public regardless of whether you type it in that
925923
// way.)
926924
public void run () {
@@ -975,7 +973,7 @@ class ThreadTester {
975973
// 得到新的执行线程。在启动线程前,线程还不成其为线程。
976974
// 在启动 Thread 实例之前,他就跟其他的对象一样,
977975
// 只是个 Tread 的实例,而不会有任何真实的 “线程特征”(
978-
// Before that, it's just a Thread instance, like any
976+
// Before that, it's just a Thread instance, like any
979977
// other object, but it won't have any real 'threadness')。
980978
myThread.start();
981979

@@ -1196,7 +1194,7 @@ public class MyRunnable implements Runnable {
11961194
}
11971195

11981196
public void doMore () {
1199-
1197+
12001198
// 在这里调用 sleep() 将强制新线程离开当前运行状态!
12011199
try {
12021200
Thread.sleep(2000);
@@ -1244,7 +1242,7 @@ public class RunThreads implements Runnable {
12441242
// 给这两个线程取名字。
12451243
alpha.setName("Alpha thread");
12461244
beta.setName("Beta thread");
1247-
1245+
12481246
// 启动这两个线程。
12491247
alpha.start();
12501248
beta.start();
@@ -1269,7 +1267,7 @@ public class RunThreads implements Runnable {
12691267
经测试(重复运行 20 遍),上面的代码,运行的结果均为:
12701268

12711269
```console
1272-
$ java -jar build/libs/com.xfoss.learningJava-0.0.1.jar
1270+
$ java -jar build/libs/com.xfoss.learningJava-0.0.1.jar
12731271
Alpha thread is running.
12741272
Alpha thread is running.
12751273
Alpha thread is running.
@@ -1301,7 +1299,7 @@ public class RunThreads implements Runnable {
13011299
// 给这两个线程取名字。
13021300
alpha.setName("Alpha thread");
13031301
beta.setName("Beta thread");
1304-
1302+
13051303
// 启动这两个线程。
13061304
alpha.start();
13071305
beta.start();
@@ -1330,7 +1328,7 @@ public class RunThreads implements Runnable {
13301328
运行结果就变成:
13311329

13321330
```console
1333-
$ java -jar build/libs/com.xfoss.learningJava-0.0.1.jar
1331+
$ java -jar build/libs/com.xfoss.learningJava-0.0.1.jar
13341332
Alpha thread is running.
13351333
Beta thread is running.
13361334
Beta thread is running.
@@ -1344,7 +1342,7 @@ Alpha thread is running.
13441342
```
13451343

13461344
```console
1347-
$ java -jar build/libs/com.xfoss.learningJava-0.0.1.jar
1345+
$ java -jar build/libs/com.xfoss.learningJava-0.0.1.jar
13481346
Alpha thread is running.
13491347
Beta thread is running.
13501348
Alpha thread is running.
@@ -1358,7 +1356,7 @@ Beta thread is running.
13581356
```
13591357

13601358
```console
1361-
$ java -jar build/libs/com.xfoss.learningJava-0.0.1.jar
1359+
$ java -jar build/libs/com.xfoss.learningJava-0.0.1.jar
13621360
Alpha thread is running.
13631361
Beta thread is running.
13641362
Beta thread is running.
@@ -1563,7 +1561,7 @@ public class RyanAndMonicaJob implements Runnable {
15631561

15641562
String currentThread = Thread.currentThread().getName();
15651563

1566-
System.out.format("%s 即将进行支取,数额为 %d, 此时余额为 %d\n",
1564+
System.out.format("%s 即将进行支取,数额为 %d, 此时余额为 %d\n",
15671565
currentThread, amount, account.getBalance());
15681566

15691567
// 检查余额,在余额不足以进行支取时,只打印一条消息。而有
@@ -1580,7 +1578,7 @@ public class RyanAndMonicaJob implements Runnable {
15801578
System.out.format("%s 醒过来了\n", currentThread);
15811579

15821580
account.withdraw(amount);
1583-
System.out.format("%s 完成了支取,支出数额 %d, 此时账户余额为 %d\n",
1581+
System.out.format("%s 完成了支取,支出数额 %d, 此时账户余额为 %d\n",
15841582
currentThread, amount, account.getBalance());
15851583
}
15861584
else {
@@ -1595,7 +1593,7 @@ public class RyanAndMonicaJob implements Runnable {
15951593
该程序某次运行的输出为:
15961594

15971595
```console
1598-
$java -jar build/libs/com.xfoss.learningJava-0.0.1.jar  ✔
1596+
$java -jar build/libs/com.xfoss.learningJava-0.0.1.jar  ✔
15991597
Monica 即将进行支取,数额为 80, 此时余额为 100
16001598
Ryan 即将进行支取,数额为 30, 此时余额为 100
16011599
Ryan 即将睡过去
@@ -1690,7 +1688,7 @@ private synchronized void makeWithdrawal (int amount) {
16901688

16911689
String currentThread = Thread.currentThread().getName();
16921690

1693-
System.out.format("---------\n%s 即将进行支取,支取数额为 %d\n",
1691+
System.out.format("---------\n%s 即将进行支取,支取数额为 %d\n",
16941692
currentThread, amount, account.getBalance());
16951693

16961694
if (account.getBalance() >= amount){
@@ -1703,7 +1701,7 @@ private synchronized void makeWithdrawal (int amount) {
17031701
System.out.format("%s 醒过来了\n", currentThread);
17041702

17051703
account.withdraw(amount);
1706-
System.out.format("%s 完成了支取,支出数额 %d, 此时账户余额为 %d\n",
1704+
System.out.format("%s 完成了支取,支出数额 %d, 此时账户余额为 %d\n",
17071705
currentThread, amount, account.getBalance());
17081706
}
17091707
else {
@@ -2215,8 +2213,8 @@ public class SimpleChatClient extends JFrame {
22152213
// 了一个新线程。该线程的作业,是从服务器的套接字流进行读取,之后
22162214
// 在滚动文本区显示出全部传入消息。
22172215
//
2218-
// We're starting a new thread, using a new inner class as the
2219-
// Runnable(job) for the thread. The thread's job is to read
2216+
// We're starting a new thread, using a new inner class as the
2217+
// Runnable(job) for the thread. The thread's job is to read
22202218
// from the server's socket stream, displaying any incoming
22212219
// messages in the scrolling text area.
22222220
Thread readerThread = new Thread(new IncomingReader());
@@ -2351,7 +2349,7 @@ public class VerySimpleChatServer {
23512349
} catch (Exception ex) {ex.printStackTrace();}
23522350
}
23532351
}
2354-
2352+
23552353
public void tellEveryOne(String message) {
23562354
Iterator it = clientOutputStreams.iterator();
23572355

@@ -2386,7 +2384,7 @@ public class VerySimpleChatServer {
23862384
> 事实上,这里就 *应该* 把这些方法同步化,以阻止其他线程以别的方式来访问这些方法。由于这里的示例并没有其他代码会读写到银行账户,因此就没有那样做(Actually, we *should* have synchronized those methods, to prevent other threads from accessing those methods in other ways. We didn't bother, because our example didn't have any other code accessing the account)。
23872385
>
23882386
> 不过需要补充的是,对读取器与设置器(或者说这个示例中的 `checkBalance()` 与 `withdraw()`)的同步化,是不充分的。请记住,同步化的点位,是要令到某个特定代码部分以 **原子方式** 工作。也就是说,同步化不光是所要关注的一些单个方法,而是那些要求 **多个步骤去完成** 的方法!请稍加思考。假如这里没有将 `makeWithdrawl()`方法同步化,Ryan 就会检查完账户余额(通过调用同步化的 `checkBalance()` 方法),然后立即退出该方法并交回那把钥匙(But synchronizing the getters and setters(or in this case the `checkBalance()` and `withdraw()`) isn't enough. Remember, the point of sysnchronization is to make a specific section of code work ATOMICALLY. In other words, it's not just the individual methods we care about, it's methods that requires ***more than one step to complete***! Think about it. If we had not synchronized the `makeWithdrawal()` method, Ryan would have checked the balance(by calling the synchronized `checkBalance()`), and then immediately exited the method and returned the key)!
2389-
>
2387+
>
23902388
> 当然他就在他醒来后,再度取得那把钥匙,这样他就可以调用那个同步的 `withdraw()`方法,然而这样做仍留下了在同步化之前曾遇到过的同样问题!Ryan能够检查余额、睡过去,然后 Monica 就可以进入并在 Ryan 有机会醒来且完成他的提取之前,对余额进行检查(Of course he would grad the key again, after he wakes up, so that he can call the synchronized `withdraw()` method, but this still leaves us with the same problem we had before synchronization! Ryan can check the balance, go to sleep, and Monica can come in and also check the balance before Ryan has a chance to wakes up and completes his withdrawal)。
23912389
>
23922390
>因此将全部存取方法进行同步化,从而阻止其他线程介入,可能是个不错的主意,但仍需把那些具有必须以一个原子单元方式执行语句的方法,加以同步化(So synchronizing all the access methods is probably a good idea, to prevent other threads from getting in, but you still need to synchronizing the methods that have statements that must execute as one atomic unit)。
@@ -2442,20 +2440,20 @@ public class BeatBoxFinal extends JFrame{
24422440
JLabel tempoLabel = null;
24432441

24442442
String [] instrumentNames = {
2445-
"贝斯鼓(低音鼓)",
2443+
"贝斯鼓(低音鼓)",
24462444
"闭镲(闭合击镲)",
2447-
"空心钹(开音踩钹)",
2448-
"小鼓(军鼓)",
2449-
"双面钹(强音钹)",
2445+
"空心钹(开音踩钹)",
2446+
"小鼓(军鼓)",
2447+
"双面钹(强音钹)",
24502448
"拍手(拍掌声)",
2451-
"高音鼓(高音桶鼓)",
2452-
"高音圆鼓(高音小鼓)",
2453-
"沙锤(沙铃)",
2454-
"口哨",
2449+
"高音鼓(高音桶鼓)",
2450+
"高音圆鼓(高音小鼓)",
2451+
"沙锤(沙铃)",
2452+
"口哨",
24552453
"低音手鼓",
2456-
"牛铃(牛颈铃)",
2457-
"颤音叉",
2458-
"中低音桶鼓",
2454+
"牛铃(牛颈铃)",
2455+
"颤音叉",
2456+
"中低音桶鼓",
24592457
"高音撞铃",
24602458
"开音高音手鼓"};
24612459

@@ -2534,7 +2532,7 @@ public class BeatBoxFinal extends JFrame{
25342532
btnDownTempo.addActionListener(new DownTempoListener());
25352533
btnBox.add(btnDownTempo);
25362534

2537-
tempoLabel = new JLabel(String.format("速度因子:%.2f", 1.00f));
2535+
tempoLabel = new JLabel(String.format("速度因子:%.2f", 1.00f));
25382536
btnBox.add(tempoLabel);
25392537

25402538
JButton sendItBtn = new JButton("发出🚀");
@@ -2598,7 +2596,7 @@ public class BeatBoxFinal extends JFrame{
25982596
// 使用那个矢量值,作为在那个清单中显式内容的源。
25992597
//
26002598
// When a message comes in, we read(deserialize) the two objects(the
2601-
// message and the ArrayList of Boolean checkbox state values) and
2599+
// message and the ArrayList of Boolean checkbox state values) and
26022600
// add it to the JList component. Adding to a JList is a two-step
26032601
// thing: you keep a Vector of the lists data(Vector is an old-fashioned
26042602
// ArrayList), and then tell the JList to use that Vector as it's source for

0 commit comments

Comments
 (0)