首页 » java » 正文

java程序设计进阶复习笔记

  1. synchronized只能同步方法,不能同步变量

  2. 非同步方法不受影响,同步方法只能进入一个。

  3. 线程休眠,锁不会释放。

  4. 同步损害并发性,应当尽可能减少同步范围。

  5. notify()是随机的唤醒一个等待的线程,本线程继续执行。notifyAll()唤醒所有线程,本线程继续执行。

  6. wait、notify、notifyAll三个方法是Object类的,所有对象都能调用。

  7. 有种巧妙点的是限定先拿小的。

  8. 高优先级线程通过sleep给低优先级执行的机会,yield只是给同优先级的执行机会。

  9. 不可变:线程安全的,根本就不能被改变。

  10. 绝对线程安全、相对线程安全。

  11. 线程兼容:对象本身不是线程安全的,但是可以通过在调用端正确的使用同步手段来保证对象在并发环境中可以安全使用。

  12. 线程对立:无论调用端是否采取了同步措施,都无法再多线程环境中并发使用的代码。

  13. 互斥同步:临界区、互斥量、信号量。

  14. synchronized关键字经过编译后,会在同步快前后形成monitorewter和monitorexit两个字节码。有线程执行到此,会阻塞后面接下来的。

  15. 阻塞同步:通过阻塞和唤醒来进行同步,有性能不高的问题。悲观并发策略。

  16. 非阻塞同步:基于冲突检测的乐观并发策略,先进行操作,如果没有其他线程征用共享数据,则操作成功;否则就是操作产生了冲突,采取不断重试直到成功为止的策略,称为非阻塞同步。

  17. 可重入代码:中断去执行另一段代码,回来继续执行当前代码,数据不会有差别。

  18. 线程本地存储:控制数据的操作范围在一个线程内执行。

  19. ThreadLocal类是个神奇的东西,神奇到还不是很懂。

  20. 自旋锁、自适应锁、锁消除、锁粗化、偏向锁。

  21. URL、URLConnection,openConnection是个连接的对象,还需要调用connect方法才是连接。

public class Main {
    public static void main(String args[]){
        try{
            URL url = new URL("https://www.sina.com");
            URLConnection urlConnection = url.openConnection();
            BufferedReader in = new BufferedReader(
                    new InputStreamReader(urlConnection.getInputStream())
            );
            String line;
            while((line = in.readLine()) != null){
                System.out.println(line);
            }
            in.close();
        }catch (MalformedURLException e){
            e.printStackTrace();
        }catch (IOException ex){
            ex.printStackTrace();
        }

    }
}

  1. Get请求的方法
public class Main {
    public static void main(String args[]){
        String str = sendGet("https://xuanqis.com","");
        System.out.println(str);
    }

    public static String sendGet(String url, String param){
        String result ="";
        BufferedReader in = null;
        try{
            String realURLName = url+"?"+param;
            URL realURL = new URL(realURLName);
            //建立连接的对象
            URLConnection connection = realURL.openConnection();
            //设置请求的属性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            //建立实际的连接
            connection.connect();
            //定义BufferedRead来读取URL的响应
            in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String line ;
            while((line = in.readLine()) != null){
                result+=line+"\n";

            }
            in.close();
        }catch (MalformedURLException e){
            e.printStackTrace();
        }catch (IOException ex){
            ex.printStackTrace();
        }
        finally {
            return result;
        }
    }
}
  1. Post请求的方法,注意需要对象允许输出流,另外怎么将参数传过去还不是很懂,可能是一个已经形成的整个请求体。
public class Main {
    public static void main(String args[]){
        String str = sendPost("https://xuanqis.com","haha");
        System.out.println(str);
    }

    public static String sendPost(String url, String param){
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try{
            URL realURL = new URL(url);
            //打开连接
            URLConnection connection = realURL.openConnection();
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            //还需要允许输出流
            connection.setDoOutput(true);
            //获取输出流
            out=new PrintWriter(connection.getOutputStream());
            out.print(param);
            out.flush();
            in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String line ;
            while((line = in.readLine()) != null){
                result+=line+"\n";
            }
            in.close();
        }catch (MalformedURLException e){
            e.printStackTrace();
        }catch (IOException e1){
            e1.printStackTrace();
        }finally{
            return result;
        }
    }
}

  1. HttpURLConnection类里面封装了很多有用的字段和方法

  2. socket的自己尝试

public class Server {
    public static void main(String args[]){
        Socket socket = null;
        try{
            ServerSocket server = new ServerSocket(8080);
            socket = server.accept();
            System.out.println("连接成功!");
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
            String line ;
            while((line = in.readLine()) != null){
                System.out.println(line);
                out.print(line+"\n");
                out.flush();
            }
            in.close();
            out.close();
            socket.close();
            server.close();
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

public class Client {
    public static void main(String args[]){
        try{
            Socket socket = new Socket("127.0.0.1", 8080);
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
            String line;
            out.print("你好!\n");
            out.flush();
            line = in.readLine();
            while(!line.equals("bye")){
                System.out.println(line);
                out.print(line+"\n");
                out.flush();
                line = in.readLine();
            }
            System.out.println("bye");
            in.close();
            out.close();
            socket.close();
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

  1. udp限定传输64K以下,典型应用是ping

  2. 构造方法
    DatagramSocket()
    DatagramSocket(int port)
    DatagramPacket(byte ibuf[], int ilength);
    DatagramPacket(byte ibuf[], int ilength, InetAddress iaddr, int iport);

  3. 收数据报:

DatagramPacket packet = new DatagramPacket(buf, 256);  
socket.receive(packet);

发数据报:

DatagramPacket packet = new DatagramPacket(buf,buf.length,address, port);
socket.send(packet);  
  1. 数据报的使用
public class Server {
    public static void main(String args[]) throws IOException{
        new QuoteServerThread("haha").start();
    }
}

class QuoteServerThread extends Thread{
    protected DatagramSocket socket = null;
    protected BufferedReader in = null;
    protected boolean moreQuotes = true;
    public QuoteServerThread(String name) throws IOException{
        super(name);
        socket = new DatagramSocket(8080);
        in = new BufferedReader(new FileReader("temp.txt"));
    }
    public void run(){
        while(moreQuotes){
            try{
                byte[] buf = new byte[256];
                DatagramPacket packet = new DatagramPacket(buf, buf.length);
                socket.receive(packet);
                String str = null;
                if(in==null) str=new Date().toString();
                else {
                    str = get();  
                }
                buf =str.getBytes();
                InetAddress address = packet.getAddress();
                int port = packet.getPort();
                packet= new DatagramPacket(buf, buf.length, address, port);
                socket.send(packet);
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            socket.close();
        }
    }
    protected String get(){
        String value=null;
        try{
            if((value = in.readLine()) == null){
                in.close();
                moreQuotes=false;
                value="No";  
            }

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            return value;
        }
    }
}
public class Client {
    public static void main(String args[]){
        DatagramSocket socket=null;
        byte[] buf = new byte[256];
        try{
             socket = new DatagramSocket();
            InetAddress address = InetAddress.getByName("127.0.0.1");
            DatagramPacket packet = new DatagramPacket(buf, buf.length,address,8080);
            socket.send(packet);
            packet = new DatagramPacket(buf, buf.length);
            socket.receive(packet);
            String received=new String(packet.getData());
            System.out.println(received);
        }catch (SocketException e){
            e.printStackTrace();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

  1. 多点广播
public class Test {

    private final static String BC_IP = "230.0.0.1"; // 组播地址
    private final static int BC_PORT = 30000; // 组播端口
    private final static int PACK_SIZE = 4096;

    public void init() throws IOException {
        MulticastSocket sock = new MulticastSocket(BC_PORT);
        InetAddress bcAddr = InetAddress.getByName(BC_IP);
        try (Scanner scan = new Scanner(System.in)) {
            // 创建socket并加入组播地址
            sock.joinGroup(bcAddr);
            sock.setLoopbackMode(false); // 必须是false才能开启广播功能!!

            new Thread(() -> { // 接受广播消息的线程
                try {
                    DatagramPacket inpack = new DatagramPacket(new byte[PACK_SIZE], PACK_SIZE);
                    while (true) {
                        sock.receive(inpack);
                        System.out.println("广播消息:" + new String(inpack.getData(), 0, inpack.getLength()));
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    if (sock != null) {
                        try {
                            sock.leaveGroup(bcAddr);
                        } catch (Exception e1) {
                            // TODO Auto-generated catch block
                            e1.printStackTrace();
                        }
                        sock.close();
                    }
                    System.exit(1);
                }
            }).start();
            // 主线程接受控制台输入并广播出去
            DatagramPacket outpack = new DatagramPacket(new byte[0], 0, bcAddr, BC_PORT); // 目的端口和MulticastSocket端口一样!!
            while (scan.hasNextLine()) {
                byte[] buf = scan.nextLine().getBytes();
                outpack.setData(buf);
                sock.send(outpack);
            }
        } finally { // 最终关闭程序之前一定要关闭socket
            sock.close();
        }
    }
    public static void main(String[] args) throws NumberFormatException, IOException {
        // TODO Auto-generated method stub
        new Test().init();
    }
}

发表评论