JAVA简明摘要(十五)网络联机(网络与线程)

1 Socket连接

1.连接
2.传送
3.接收

Socket chatSocket = new Socket("196.164.1.103", 5000);

端口号有16位宽,范围为0-65535,其中0-1023都被保留给已知的特定服务。
网页服务器是80。Telnet服务器是23。POP3邮件服务器是110。SMTP邮局交换服务是25。

2 读取Socket

127.0.0.1这个IP地址代表本机,所以可以在本机同时测试客户端和服务器。

//1.建立对服务器的Socket连接
Socket chatSocket = new Socket("127.0.0.1",5000);

//2.建立连接到Socket低层输入串流的InputStreamReader,InputStreamReader转换字节为字符
InputStreamReader stream = new InputStreamReader(chatSocket.getInputStream());

//3.建立BufferedReader来读取
BufferedReader reader = new BufferedReader(stream);
String message = reader.readLine();

3 写入Socket

Socket chatSocket = new Socket("127.0.0.1",5000);

PrintWriter stream = new PrintWriter(chatSocket.getOutputStream());

writer.println("message to send");
writer.print("another message");

4 客户端

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.logging.SocketHandler;

public class DailyAdviceClient {
    public static void main(String[] args) {
        DailyAdviceClient client = new DailyAdviceClient();
        client.go();
    }//end main

    public void go() {
        try {
            Socket s = new Socket("127.0.0.1", 4242);

            InputStreamReader streamReader = new InputStreamReader(s.getInputStream());
            BufferedReader reader = new BufferedReader(streamReader);

            String advice = reader.readLine();
            System.out.println("Today you should " + advice);

            reader.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }//end go
}

5 服务器

服务器需要一对Socket,一个是会等待用户请求的ServerSocket,一个是与用户通信用的Socket。

1.服务器应用程序对特定端口创建出ServerSocket。
ServerSocket serverSock = new ServerSocket(4242);

2.服务器端创建出与客户端通信的Socket
Socket sock = serverSock.accept();
accept()方法会在等待用户的Socket连接时闲置。当用户连上来时,此方法会返回一个Socket(在不同的端口上),以便与客户端通信。Socket与ServerSocket的端口不同,因此ServerSocket可以空出来等待其他用户。

6 服务器端

import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class DailyAdviceServer {
    String [] adviceList = {"Take small bites", "Go for the tight jeans", "Happy", "Sad", "Cry"};
    public void go() {
        try {
            System.out.println("begin");

            ServerSocket serverSocket = new ServerSocket(4242);
            while(true) {
                //该方法会停下来等待要求到达后才会继续
                Socket socket = serverSocket.accept();
                PrintWriter writer = new PrintWriter(socket.getOutputStream());
                String advice = getAdvice();
                writer.println(advice);
                writer.close();

            }//end while
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }//end go

    private String getAdvice() {
        int random = (int) (Math.random() * adviceList.length);
        return adviceList[random];
    }

    public static void main(String[] args) {
        DailyAdviceServer server = new DailyAdviceServer();
        server.go();
    }

}

7 线程

1.建立Runnable对象(线程的任务)
Runnable threadJob = new MyRunnable();

2.建立Thread对象(执行工人)并赋值Runnable(任务)
Thread myThread = new Thread(threadJob)

3.启动Thread
myThread.start()

每个Thread需要一个任务来执行。该任务即
public void run() {
}

不同线程可以命名
(通常用来除错)

Thread alpha = new Thread(runner);
alpha.setName("Alpha thread");

String threadName = Thread.currentThread().getName();

8 线程调度器

无法控制调度,没有API可以调用调度器。

9 Runnable接口

接口可以用来声明子类

public class MyRunnable implements Runnable {
    public void run() {
        go();
    }//end run
    public void go() {
        doMore();
    }
    public void doMore() {
        System.out.println("Hello");
    }
}


public class ThreadTester {
    public static void main(String[] args) {
        MyRunnable threadJob = new MyRunnable();
        Thread myThread = new Thread(threadJob);
        myThread.start();
        System.out.println("main");
    }
}

可以不使用Runnable接口,用Thread的子类覆盖run()这个方法,然后调用Thread的无参数构造函数来创建出新的线程。
一旦线程的run()方法完成之后,该线程就不能再重新启动。

10 sleep()

确保其他线程能够有机会执行的最好方式是让它们周期性地休眠。
Thread.sleep(2000);
需要包在try/catch块中。

11 并发

多线程会引发并发性,并发性会引发竞争状态,竞争状态会引发数据的损毁。
两个或以上的线程存取单一对象的数据,即两个线程都对同一个对象执行getter或setter。

12 锁

每个对象都有一把锁,大部分时间都没有锁上,对象的锁只会在有同步化的方法上起作用。
如果对象有两个同步化的方法,就表示两个线程无法进入同一个方法,也表示两个线程无法进入不同的方法。
private synchronized void makeWithDraw(int amount) {
}

同步化会带来额外的成本。
查询钥匙等性能的损耗。
强制线程排队使进程变慢。
可能会导致死锁现象。

同步化可以只修饰部分指令,不必整个方法都同步化。

public void go() {
  doStuff();
  
  synchronized(this) {
    criticalStuff();
    morecriticalStuff();
  }
}

13 死锁

数据库有处理死锁的机制,Java没有。
只要两个线程和两个对象就可以引起死锁。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值