JAVA学习笔记3

来源:互联网 发布:阿芙 知乎 编辑:程序博客网 时间:2024/05/17 03:05

2011.8.8       周五

1.文字也可以用字节流读写 --文件存在则覆盖掉

 FileOutputStream(File file, booleanappend)  创建一个向指定 File 对象表示的文件中写入数据的文件输出流 ,如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处.

2.控制写入换行 fos.write(‘\n’);

3.DataInputStream andDataOutputStream  数据输入输出流 - 处理流

  能够应用于Java原始类型的读写操作构造方法

   DataInputStream(InputStreamin)

    DataOutputStream(OutputStreamout)

其他方法   

  readBoolean()/writeBoolean()

  readByte()/writeByte() 从所包含的输入流中读取此操作需要的字节

  readChar()/writeChar()   从包含的输入流中读取此操作需要的字节

  ReadInt()/WriteInt(i)  返回/写入整数

怎样写入代码就要怎样输出代码。

 

 

 


                                   写入1-10

 

 

实例:

import java.io.*;

/**

 * 数据流  专门针对原始类型

 */

public class DataStreamTest {

    public static void main(String[] args) {

        try {

            DataOutputStream dos     //写  (内容看不懂)

                = new DataOutputStream(new FileOutputStream("c.txt"));

           

            for(int i=0;i<=10;i++){

                dos.writeInt(i);

            }

            dos.writeDouble(0.1);

            dos.close();

 

            DataInputStream dis     //读

            = new DataInputStream(new FileInputStream("c.txt"));

           

            for(int i=0;i<=10;i++){

                int b = dis.readInt();

                System.out.println(b);

            }

            System.out.println(dis.readDouble()); 

        } catch (FileNotFoundException e) {

            e.printStackTrace();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}

4.PipedInputStream andPipedOutputStream    管道输入输出流

   一个管道输入流连接一个管道输出流

   是一种线程之间交换数据的通讯方法

构造方法

    PipedInputstream()

    PipedInputStream(PipedOutputStreamsrc)

    PipedOutputStream()

PipedOutputStream(PipedInputStreamsink)

5.Reading and Writing  with RandomAccessFile  随机存取文件流的读/写

   实现了DataInput和 DataOutput接口

   当打开一个文件时,提供了即能读又能写的能力

   通过使用文件指针可以对文件的特定位置读写

构造方法

  RandomAccessFile(Filefile, String mode)

  RandomAccessFile(Stringfilename, String mode)

其他方法

   read()/write()  seek(long pointer)

6.PrintStream字节打印输出流  既是节点流又是处理流  注意:内容会覆盖

构造方法

PrintStream(File file)
         
创建具有指定文件且不带自动行刷新的新打印流。

PrintStream(File file, String csn)
         
创建具有指定文件名称和字符集且不带自动行刷新的新打印流。

PrintStream(OutputStream out)
         
创建新的打印流。

PrintStream(OutputStream out, boolean autoFlush)
         
创建新的打印流。

PrintStream(OutputStream out, boolean autoFlush, String encoding)
         
创建新的打印流。

PrintStream(String fileName)
         
创建具有指定文件名称且不带自动行刷新的新打印流。

PrintStream(String fileName, String csn)
         
创建具有指定文件名称和字符集且不带自动行刷新的新打印流。

其它方法:

Void print()打印对象。

Void void()将指定的字节写入此流。

staticPrintStream  out  “标准”输出流、类型是PrintStream

PrintStream(OutputStream out, booleanautoFlush, Stringencoding) 创建新的打印流。
实现追加用处理流 在OutputStream指明可追加

System.Out  Out是标准输出流打印数据到控制台

importjava.io.FileNotFoundException;

importjava.io.FileOutputStream;

importjava.io.PrintStream;

/**

 * 字节打印流  

 * 既是节点流又是处理流

 */

public classPrintStreamTest {

       public static void main(String[] args) {

              try{

                     //PrintStream ps = newPrintStream("d.txt");

                     PrintStream ps = new PrintStream(newFileOutputStream("d.txt",true));

                     ps.println("adsfadsfsadf");

                     ps.println(1212);

                     ps.close();

              }catch (FileNotFoundException e) {

                     e.printStackTrace();

              }

       }

}

思考:

  如何将数据输出到文件Log.txt

//static voidsetOut(PrintStream out)重新分配标准输出流。

importjava.io.FileNotFoundException;

importjava.io.FileOutputStream;

import java.io.PrintStream;

public classOutTest {

       public static void main(String[] args) {

              /**

               * System.out  out标准输出流

               * 打印数据到控制台

               */

              System.out.println("out是标准输出流,输出到控制台");

              /**

               * System.out.println()输出内容到文件log.txt

               */

              try{

                                                                                                        

可追加

 

 


System.setOut(new PrintStream(newFileOutputStream("log.txt",true)));

              }catch (FileNotFoundException e) {

                     e.printStackTrace();

              }

              System.out.println("out输出内容内容进入log日志文件");

       }

}

如果要让整个工程起作用,写一个类:

public class Debug {

    static{

        try {

            System.setOut(new PrintStream

                    (new FileOutputStream("log.txt",true)));

        } catch (FileNotFoundException e) {

            e.printStackTrace();

        }

    }

    public static void debug(Classc,Object o){

        System.out.println(c.getName()+"==="+new Date()+"==="+o);

    }

}调用:

public class DebugTest {

    public static void main(String[] args) {

        System.out.println("hello");

        Debug.debug(DebugTest.class,"hello");

    }}

7.Unicode编码和其他编码之间的转换

 

 

 

 

 

 

 

 

 

 

 

 

 

 

常用:GB2312:简体中文

      GBK  国标码(简体+繁体)默认是GBK

      UTF-8 通用码 (简体+繁体+英文)

注意:解码要与编码同步

String(byte[] bytes,String charsetName)
          通过使用指定的charset 解码指定的 byte 数组,构造一个新的String

public class CharacterEcodingTest {

    public static void main(String[] args) {

        String str = "中国";

        try {

        Strings tr2= new String(str.getBytes("ISO-8859-1"),"GBK");

            System.out.println(str);

            System.out.println(str2);

        } catch (UnsupportedEncodingException e) {

            e.printStackTrace();

        }

    }

}

8.Reader and Writer  字符流读/写器    抽象类

  Reader和Writer是用于读写字符流的抽象类

 他们的子类必须实现:

read(char[], int, int)

write(char[], int, int)

close()

flush()

 

 

 

 

 

 

 

 

 

 


Reader:

BufferedReader,CharArrayReader,FileReader,InputStreamReader,PipedReader,StringReader

Writer:

BufferedWriter,CharArrayWriter,FilterWriter,OutputStreamWriter,PipedWriter,PrintWriter,StringWriter

Reader构造方法:

Reader()     创建一个新的字符流 reader,其重要部分将同步其自身的 reader。

Reader(Object lock)  创建一个新的字符流 reader,其重要部分将同步给定的对象。

 

Writer构造方法:

  Writer() 创建一个新的字符流 writer,其关键部分将同步 writer 自身。

  Writer(Object lock) 创建一个新的字符流 writer,其关键部分将同步给定的对象。

9.FileReader and FileWriter  文件字符输入/输出流   节点流

   方便了字符文件的读/写

 构造函数

    FileReader(File file)

    FileReader(String name)

    FileWriter(File file)

    FileWriter(String filename)

public class FileNavTestReader {

    public static void main(String[] args) {

        File src = newFile("src/sample/FileNavTest.java");

        try {

            FileInputStream fis = new FileInputStream(src);

            int b =0;

            while((b=fis.read())!=-1){

                System.out.print((char)b);

            }

            fis.close();

        } catch (FileNotFoundException e) {

            e.printStackTrace();

        } catch (IOException e) {

            e.printStackTrace();

        }

        File src = newFile("src/sample/FileNavTest.java");

        try {

            FileReader fr = new FileReader(src);

            int b = 0;

            while((b=fr.read())!=-1){

                System.out.print((char)b);

            }

            fr.close();

        } catch (FileNotFoundException e) {

            e.printStackTrace();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}

10.BufferedReader and BufferedWriter带有缓冲区的字符输入/输出流 处理流可以读一行

   PrintWriter 向文本输出流打印对象的格式化表示形式 

  对字符进行缓冲从而提高读/写字符的效率

 

构造函数:

  BufferedReader(Reader in)

  BufferedReader(Reader in, int size)

  BufferedWriter(Writer out)

  BufferedWriter(Writer out, int size)

PrintWriter :

构造方法摘要

PrintWriter(File file)       字节流
         
使用指定文件创建不具有自动行刷新的新 PrintWriter

PrintWriter(File file, String csn) 字节流
         
创建具有指定文件和字符集且不带自动刷行新的新 PrintWriter

PrintWriter(OutputStream out)

           根据现有的 OutputStream创建不带自动行刷新的新 PrintWriter

PrintWriter(OutputStream out, boolean autoFlush)
         
通过现有的 OutputStream创建新的 PrintWriter

PrintWriter(String fileName)

创建具有指定文件名称且不带自动行刷新的新 PrintWriter

PrintWriter(String fileName, String csn)
         
创建具有指定文件名称和字符集且不带自动行刷新的新 PrintWriter

PrintWriter(Writer out) 创建不带自动行刷新的新 PrintWriter

PrintWriter(Writer out, boolean autoFlush)   创建新 PrintWriter

其他方法

   readLine() 读一行

   newLine () 产生一个空行

   Flush() 自动刷新

BufferedReader实例:

importjava.io.BufferedReader;

importjava.io.FileNotFoundException;

import java.io.FileReader;

importjava.io.IOException;

 

public classBufferedReaderTest {

       public static void main(String[] args) {

              try{

                     //带缓冲的字符输入流    可以readLine()读一行

                     BufferedReader br =

                            newBufferedReader(new FileReader("music.db"));

                     String str ="";

                     while((str=br.readLine())!=null){

                            System.out.println(str);

                     }

                     br.close();

                    

              }catch (FileNotFoundException e) {

                     e.printStackTrace();

              }catch (IOException e) {

                     e.printStackTrace();

              }

       }

}

PrintWriter实例:

importjava.io.FileNotFoundException;

importjava.io.FileWriter;

importjava.io.IOException;

importjava.io.PrintWriter;

public classPrintWriterTest {

       public static void main(String[] args) {

              try{

                     //创建字符打印流   自动刷新

                     PrintWriter pw = new PrintWriter(newFileWriter("e.txt"),true);

                     pw.println("printwriter 写数据");

                     pw.close();

              }catch (FileNotFoundException e) {

                     e.printStackTrace();

              }catch (IOException e) {

                     e.printStackTrace();

              }

       }

}

11.InputStreamReader and OutputStreamWriter  字节和字符之间转换的输入输出流(桥梁流)

  InputStreamReader 是字节流转换字符流的桥梁

  outputStreamWriter  是字符流转换字节流的桥梁

构造方法

  InputStreamReader(InputStream in, StringcharsetName)

  OutputStreamWriter(OutputStream out, StringcharsetName)

读键盘输入的一行内容:

    BufferedReader br=

new BufferedReader(newInputStreamReader(System.in));

    String str = br.readLine();

public class PrintWriterTest2 {

    public static void main(String[] args) {

        try {

            /**

             * 通过键盘输入数据System.in  InputStream

             * 要读键盘输入的一行数据  要使用BufferedReader

             * BufferedReader(Reader r)  无法嵌套InputStream

             * 考虑:桥梁流

             * Reader<---InputStreamReader(InputStreamin)

             */

            System.out.println("等待键盘输入数据:");

            BufferedReader br=

                new BufferedReader(new InputStreamReader(System.in));

            //键盘输入的一行数据

            String str = br.readLine();

            PrintWriter pw=newPrintWriter(newFileWriter("e.txt"),true);                 pw.println(str);

            pw.close();

        } catch (FileNotFoundException e) {

            e.printStackTrace();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}

12.Serilization 序列化

   对象持久化

   只有对象的数据被持久化了

   临时数据不能被序列化

   对象必须实现java.io.Serializable接口

* 类要想持久化 要想使用对象流传递对象  类必须实现序列化

* 类实现Serializable接口没有任何抽象方法 就是序列化的标志

public class Student implements Serializable{

   //private transient String name;临时数据不能被序列化

    private  String name;

    private int age;
13.ObjectInputStream and ObjectOutputStream 对象输入/输出流

  应用于对象的数据的持久化操作

  用ObjectOutputStream序列化对象,然后用OjbectInputStream再逆序列化改对象。

构造方法

  ObjectInputStream(InputStream in)

  ObjectOutputStream(OutputStream out)

其他方法

   readObject()

   writeObject()

 

public class ObjectStreamTest {

    public static void main(String[] args) {

        Student st1 = new Student("zhangsan",20);

        try {

            ObjectOutputStream oos =    newObjectOutputStream(new FileOutputStream("stu.txt"));

            //对象的序列化

            oos.writeObject(st1);

            oos.flush();

            oos.close();

            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("stu.txt"));

            //对象的反序列化

            Student s = (Student) ois.readObject();

            System.out.println(s.getName()+"  "+s.getAge());

        } catch (FileNotFoundException e) {

            e.printStackTrace();

        } catch (IOException e) {

            e.printStackTrace();

        } catch (ClassNotFoundException e) {

            e.printStackTrace();

        }

    }

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2011.8.9       周三

1.网络基础知识:

 

 

 

 

 

 

 

 

 


IP:给我们电脑提供唯一标志地址

TCP/IP协议

    OSI参考模型                  TCP/IP 参考模型

    应用层

    ------

    表示层                     应用层(app)

    ------

    会话层

    ----------------------------------------------------

    传输层                        传输层(TCP/IP)

    ---------------------------------------------------- 

    网络层                        网络层(IP)

    ----------------------------------------------------

    数据链路层

    -------                      物理层+数据链路层

    物理层

--------------------------------------------------------

TCP:可靠的、端到端的字节流通信协议,它是一种面向连接的协议。  例如:打电话。

UDP:向应用提供了一种发送封装的原始IP数据报的方法、并且发送时无需建立连接。是一种不可靠的连接。   例如:语音、视频。

区别:  TCP:可靠,慢  

    UDP:不可靠,快。  所谓的不可靠就是网络不好出现的丢包的现象。

2.Socket---中文:插座

(1)两个Java应用程序可以通过一个双向的网络通信连接实现数据交流,这个双向链路的     一端称为一个Socket。我们所说的Socket编程就是在两个应用端分别两个Socket端,然后让两个端中间相连就实现了两个应用连接。Socket通常用来实现Client-server连接   即cs结构应用

(2)类:java.net包中定义的两个类Socket和ServerSocket,分别用来实现双向连接的Client和server端。

(3)建立连接时我们需要连接计算机的ip地址和端口号(port)

端口号:区分不同的应用程序。 两个字节,最多65536。我们记住前面的1024个已经为系统的一些应用分配了, 我们自己应用时候用1024以上的。比如80端口是http应用的默认端口,21是ftp默认端口等。 Tomcat 8080  Mysql 3306 Oracle 1521

TCP端口和UDP端口是分开的,分别有65536个端口。

TCPSocket 编程模型

    两个主要类: Socket  ServerSocket

3.一个套接字就是网络上两个程序的双向连接的通信端点

 套接字必须绑定一个端口号,从而使TCP层能识别数据应该被传送的目的地。

 

 

 

 

 

 


网络地址

     Host Name(主机名)mydomain.com

     Address( 地址) 203.93.63.237

端口号:0~65535

JAVA网络模型:

 

 

 

 

 

 

 

 

 

4.Socket:客户端

    构造方法:

    Socket() 创建未连接套接字

    Socket(String host, int port)  创建一个流套接字并将其连接到指定主机上的指定端口号

    Socket(InetAddress address, int port)创建一个流套接字并将其连接到指定 IP 地址的指定端口号

   其他方法:

    getInputStream()  返回此套接字的输入流

    getOutputStream()  返回此套接字的输出流。

close()  关闭此套接字

getPort()返回此套接字连接到的远程端口。

getLocalPort()返回此套接字绑定到的本地端口。

getInetAddress() 返回套接字连接的地址。

bind(SocketAddressbindpoint) 将套接字绑定到本地地址。

getLocalAddress()  获取套接字绑定的本地地址。

5.ServerSocket服务器端  注意:只能启动一次

    构造方法:

    ServerSocket()  创建非绑定服务器套接字

    ServerSocket(int port)  创建绑定到特定端口的服务器套接字

ServerSocket(int port, int backlog)

其他方法:

   accept() 侦听并接受到此套接字的连接。

   close() 侦听并接受到此套接字的连接。 

6.网络传输的步骤:

(1)建立连接

(2)通过流发送和读取消息

(3)关闭资源

7.获得IP地址:

  InetAddress ip=InetAddress.getByName("http:\\baidu.com");

  输出:119.75.210.45

8.一个服务器端可以同时接收多个客户端,将Accept()放在While循环中

 

实例1:简单的网络编程实例

public class Server {

    public static void main(String[] args) {

        try {

        //创建一个服务器对象

            ServerSocket server = new ServerSocket(8888);

        //接收客户端连接 返回接收到的客户端对象     停滞  等待客户端连接上

            System.out.println("---服务器已经启动,等待客户端连接---");

            Socket client = server.accept(); //会停滞

            System.out.println("======客户端连接上了======");     

            client.close();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}

 

public class Client{

    public static void main(String[] args) {

        try {

            //创建客户端对象 并同时建立服务器连接

            Socket client= new Socket("127.0.0.1",8888);        

            client.close();

        } catch (UnknownHostException e) {

            e.printStackTrace();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}

 

 

实例2:服务器与客户端相互发消息

 public class Server {

    public static void main(String[] args) {

        try {

        //创建一个服务器对象

            ServerSocket server= new ServerSocket(8888);

        //接收客户端连接 返回接收到的客户端对象     停滞  等待客户端连接上

            System.out.println("---服务器已经启动,等待客户端连接---");

            Socket client = server.accept();

            System.out.println("======客户端连接上了======");     

            //向客户端写信息

            PrintWriter pw =

                new PrintWriter(client.getOutputStream());

            pw.println("客户端你好,你已经连接上服务器");

            pw.flush();      

            //创建流   读服务器端写过来的数据

            BufferedReader br =

            NewBufferedReader(NewInputStreamReader(client.getInputStream()));

            String str = br.readLine();

            System.out.println(str);

            br.close();

            pw.close();

            client.close();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}

public class Client{

    public static void main(String[] args) {

        try {

            //创建客户端对象 并同时建立服务器连接

            Socket client = new Socket("127.0.0.1",8888);

            //创建流   读服务器端写过来的数据

            BufferedReader br =

                new BufferedReader(

                    newInputStreamReader(client.getInputStream()));

            String str = br.readLine();

            System.out.println(str);

            //向服务器写数据

            PrintWriter pw =

                new PrintWriter(client.getOutputStream());   

            pw.println("客户端:服务器您好");

            pw.flush();

            pw.close();

            br.close();

            client.close();

        } catch (UnknownHostException e) {

            e.printStackTrace();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}

实例3:服务器和客户端都从键盘读取消息并发送给对方

public class Server{

    public static void main(String[] args) {

        try {

            ServerSocket server = new ServerSocket(10000);  

            System.out.println("服务器已经启动.........");    

                Socket client =server.accept();  

                //读键盘 获得数据System.in    br1.readLine()读键盘

                BufferedReader br1 =new BufferedReader(

                     new InputStreamReader(System.in));

                //键盘写的数据

                String str =br1.readLine();

                PrintWriter pw =

                    new PrintWriter(client.getOutputStream());

                pw.println(str);

                pw.flush();              

                //读客户的信息

                BufferedReader br2 =new BufferedReader(newInputStreamReader(client.getInputStream()));

                String str2 =br2.readLine();

                System.out.println(str2);

                br2.close();

                br1.close();

                pw.close();

                client.close();  

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}

public class Client3 {

    public static void main(String[] args) {

        try {

            Socket client = new Socket("localhost",10000);

           

            //读服务器信息

            BufferedReader br1 =new BufferedReader(newInputStreamReader(client.getInputStream()));

            String str = br1.readLine();

            System.out.println(str);    

            //读键盘  

            BufferedReader br2 =new BufferedReader(newInputStreamReader(System.in));

            String str2 = br2.readLine();

            //写数据给服务器

        PrintWriterpw=new PrintWriter(client.getOutputStream(),true);

            pw.println(str2);

            br1.close();

            br2.close();

            pw.close();

            client.close();          

        } catch (UnknownHostException e) {

            e.printStackTrace();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}

实例4:多个客户端同时连接服务器端

public class Server{

    public static void main(String[] args) {

        try {

        //创建一个服务器对象

            ServerSocket server = new ServerSocket(8888);

        //接收客户端连接 返回接收到的客户端对象     停滞  等待客户端连接上

            System.out.println("------服务器已经启动-------");

            int count = 1; //计数,判断第几个客户端

            while(true){ //死循环

                System.out.println("------等待客户端连接-------");

                Socket client =server.accept();

                System.out.println("第"+ count++ +"客户端连接上了,客户端端口号:"+client.getPort());

                client.close();

            }

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}

public class Client4 {

    public static void main(String[] args) {

        try {

            //创建客户端对象 并同时建立服务器连接

            Socket client = new Socket("127.0.0.1",8888);

            client.close();

        } catch (UnknownHostException e) {

            e.printStackTrace();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}

综合实例:网络聊听

public class TalkServer {

    public static void main(String[] args) {

        try {

            ServerSocket server = new ServerSocket(8888);

            System.out.println("服务器准备就绪.........");

            System.out.println("等待客户端连接......");

            Socket client= server.accept();

            //获得客户端地址

            System.out.println(client.getInetAddress());

//获得服务器的端口

            System.out.println(client.getLocalPort());

            //获得客户自己的端口

            System.out.println(client.getPort());

            System.out.println("客户端连接成功,请先输入信息聊天....");

            //读键盘

            BufferedReader br1 =

                new BufferedReader(newInputStreamReader(System.in));

            //读客户端信息流

            BufferedReader br2 =

new BufferedReader(new InputStreamReader(client.getInputStream()));

            //向客户端写信息的流 自动刷新

            PrintWriter pw=newPrintWriter(client.getOutputStream(),true);

            boolean flag =true;

            while(flag){

                String str1 =br1.readLine();

                pw.println(str1);

                if("bye".equals(str1)){//服务器向客户端bye

                    break;

                }

                String str2 =br2.readLine();

                System.out.println("【客户端说】:"+str2);

                if("bye".equals(str2)){//客户端bye

                    break;

                }

            }

            pw.close();

            br1.close();

            br2.close();

            client.close();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}

public class TalkClient {

    public static void main(String[] args) {

        try {

            Socket client = new Socket("localhost",8888);

            System.out.println("连接上服务器了,等待服务器写信息...."

            //读键盘

            BufferedReader br1 =

                new BufferedReader(new InputStreamReader(System.in));

            //读服务端信息流

            BufferedReader br2 =

newBufferedReader(new InputStreamReader(client.getInputStream()));

            //向服务端写信息的流 自动刷新

            PrintWriter pw=newPrintWriter(client.getOutputStream(),true);    

            boolean flag =true;

            while(flag){

                String str1=br2.readLine();

                System.out.println("【服务器端说】:"+str1);

                if("bye".equals(str1)){//服务器受不了

                    break;

                }

                String str2 =br1.readLine();

                pw.println(str2);

                if("bye".equals(str2)){//客户端向服务器bye

                    break;

                }

            }  

            pw.close();

            br1.close();

            br2.close();

            client.close();      

        } catch (UnknownHostException e) {

            e.printStackTrace();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2011.8.10      周三

1.URL连接

   URL和URLConnection类封装了复杂的从远端站点的获取数据的细节问题

   支持HTTP和FTP资源

     URL url = new URL(“http://mydomain.com”)

     URL url = newURL(ftp://username:password@mydomain.com)

打开一个URL连接

URLConnection urlconn =url.openConnection()

打开一个字节输入流

    InputStream in = url.openStream()

URL类是一个统一资源定位符,标识在万维网上的资源

URL的格式

    communiction protocol://hostname:port/file

构造方法:

URL(String spec) 根据 String表示形式创建 URL对象。

URL(String protocol, Stringhost, int port,String file)

 根据指定 protocolhostport号和 file创建 URL对象。

URL(String protocol, Stringhost, int port,String file,URLStreamHandlerhandler)
         
根据指定的protocolhostport号、file handler创建 URL对象。

URL(String protocol, Stringhost,Stringfile)
         
根据指定的protocol名称、host名称和 file名称创建 URL

URL(URL context, Stringspec)
          
通过在指定的上下文中对给定的spec进行解析创建 URL  

URL(URL context, Stringspec,URLStreamHandlerhandler)
        
通过在指定的上下文中用指定的处理程序对给定的 spec进行解析来创建 URL

其他方法:

equals(Object obj)   比较此 URL 是否等于另一个对象。

getContent()  获取此 URL 的内容。

getDefaultPort() 获取与此 URL 关联协议的默认端口号。

getFile() 获取此 URL 的文件名。

getHost()获取此URL 的主机名

getPort()  获取此URL 的端口号。

getProtocol()  获取此URL 的协议名称。

openConnection()
          返回一个URLConnection对象,它表示到 URL 所引用的远程对象的连接。

openStream()
          打开到此URL 的连接并返回一个用于从该连接读入的 InputStream

set(String protocol, Stringhost, int port,String file,Stringref)
          设置 URL 的字段。

2.URLConnection   抽象类

  是所有连接应用程序和URL通讯的类 的父类

构造方法:

URLConnection(URL url)
          构造一个到指定 URL 的 URL 连接。

其他方法

   connect() 打开到此 URL 引用的资源的通信链接

   getInputStream() 返回从此打开的连接读取的输入流。

   getOutputStream() 返回写入到此连接的输出流。

  实例: 

public class URLConnectionTest{ 

   public static void main(String[] args){ 

      try

         String urlName=null;

         if (args.length > 0)

             urlName = args[0]; 

         else         

             urlName="http://www.baidu.com/index.html"

         //1. get connectionobject of specified URL name

         URL url = new URL(urlName); // create URL object

 URLConnection connection =url.openConnection();

         //2. connect to the URLserver

         connection.connect();

         //3. print header fields(optional)

         int n = 1;

         String key;  

         while ((key =connection.getHeaderFieldKey(n)) !=null){ 

            String value =connection.getHeaderField(n);

            System.out.println(key +": " + value);

            n++;

         }

         //4.  print convenience functions (optional)

         System.out.println("----------");

         System.out.println("getContentType:"+connection.getContentType());

         System.out.println("getContentLength:"+connection.getContentLength());

         System.out.println("getContentEncoding:" +connection.getContentEncoding());

         System.out.println("getDate: "+ connection.getDate());

         System.out.println("getExpiration:" +connection.getExpiration());

         System.out.println("getLastModifed:" +connection.getLastModified());

         System.out.println("----------");

         //5. getInputStream fromthe URL connection (optional)

         BufferedReader in = new BufferedReader(newInputStreamReader(connection.getInputStream()));

 

         //6. print first 50 linesof contents (optional)

         String line=null;

         n = 1;

         while ((line = in.readLine()) !=null && n <= 50){// read line  from page content 

            System.out.println(line);

            n++;

         }

         if (line != null) System.out.println(". . .");

        in.close();

      } catch (IOExceptionexception){ 

           exception.printStackTrace();

      }

   }

}

3.UDP套接字

  面向无连接协议、不可靠的传输、

  DatagramSocket 和DatagramPacket  支持JAVA UDP连接

  (1)DatagramPacket类

实现了一个面向无连接的报文发送服务

从一台机器到另一台机器发送每条消息,都是独立的消息,都基于一个在这个数据包中包含到这台机器的路由信息

  构造方法:

DatagramPacket(byte[] buf, int length)
         
构造 DatagramPacket,用来接收长度为 length的数据包。

DatagramPacket(byte[] buf, int length, InetAddress address, int port)
         
构造数据报包,用来将长度为 length的包发送到指定主机上的指定端口号。

DatagramPacket(byte[] buf, int offset, int length)
         
构造 DatagramPacket,用来接收长度为 length的包,在缓冲区中指定了偏移量。

DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)
         
构造数据报包,用来将长度为 length偏移量为 offset的包发送到指定主机上的指定端口号。

DatagramPacket(byte[] buf, int offset, int length, SocketAddress address)
         
构造数据报包,用来将长度为 length偏移量为 offset的包发送到指定主机上的指定端口号。

DatagramPacket(byte[] buf, int length, SocketAddress address)
         
构造数据报包,用来将长度为 length的包发送到指定主机上的指定端口号。

 (2)DatagramSocket类

一个数据报套接字是 报文传送服务的发送或接收端

   构造方法:

    DatagramSocket()

    DatagramSocket(int port)

DatagramSocket(int port, InetAddressaddress)

 

其他方法

 connect()         Data       port

 receive()/send()

 close()

客户端

Send

                                     地址

 

 

 

 

 


     

 

 

public class UDPServer{

   public static void main(String args[]) {

        UDPServer udpServer = new UDPServer();

        udpServer.go();        

    }

    //获得时间的辅助方法

    public byte[] getTime(){

        Date d= new Date();

        return d.toString().getBytes();// String -> byte[]

    }

   // 主要的UDP Server运行程序方法

    public void go(){

    DatagramSocket datagramSocket=null;//服务器端的DatagramSocket定义

    DatagramPacket inDataPacket=null;//接收客户端的DatagramPacket

    DatagramPacket outDataPacket=null;//传给客户端的DatagramPacket

    InetAddress clientAddress=null;// 地址,这里是服务器获得客户端地址,然后发送包给客户端

     int clientPort; // 端口,这里是服务器获得客户端地址对应的端口,然后发送包给客户端  

        byte[] msg= new byte[1024];// 接收消息的数组

        byte[] time; //发送时间的数组给客户端

         try {

            //1. 创建服务器的DatagramSocket,给个端口,客户端要连接这个端口

            datagramSocket = new DatagramSocket(8000);//port 8000

            System.out.println("!!at UDPServerlocalport is: " + datagramSocket.getLocalPort());   

            while(true) {

                // 2.初始化接收客户端包

                inDataPacket = new DatagramPacket(msg, msg.length);

                // 3.获得客户端包

               datagramSocket.receive(inDataPacket);

 

                // 4.利用客户端包可以获得客户端地址和端口

                clientAddress =inDataPacket.getAddress();

                clientPort = inDataPacket.getPort();

                    System.out.println("client HostAddressis: "+clientAddress.getHostAddress()+"clientPort is : "+ clientPort  );

        time = getTime();   //初始化需要发送到客户端的时间数组

              //5. 初始化发送到客户端的包,包括两部分:发送的包和客户端地址端口

      outDataPacket = new DatagramPacket(time, time.length, clientAddress,clientPort);

                //6.服务器端最后发送数据包给客户端

               datagramSocket.send(outDataPacket);

            }

        } catch (SocketException e) {

             System.out.println ("SocketException occured with socket.");

             System.out.println (e);

             System.exit(1);

        } catch (IOException e) {

             System.out.println ("IOException occured with socket.");

             System.out.println (e);

             System.exit(1);

        } finally{

            //7.关闭Socket

           datagramSocket.close();

        }

    }

 }

public class UDPClient {

    public static void main(String args[]) {

        UDPClient udpClient = new UDPClient();

        try {

            udpClient.go();

        } catch (Exception e) {

            System.out.println ("Exception occuredwith socket.");

            System.out.println (e);

            System.exit(1);

        }

    }

   public void go() throws IOException,UnknownHostException {

  DatagramSocket datagramSocket=null//客户端DatagramSocket

  DatagramPacket outDataPacket=null;/发送给服务器端的DatagramPacket

  DatagramPacket inDataPacket=null;//从服务器端接收的DatagramPacket

        InetAddress serverAddress=null;// 需要定义个服务器端地址

        int serverPort=8000;        // 端口,这里是服务器端地址对应的端口

        byte[] msg = new byte[1024];// 发送向服务器端消息数组       

        // 1.  初始化DatagramSocket

        datagramSocket = new DatagramSocket();

            System.out.println("!!!!at UDPClient, local port is: " +datagramSocket.getLocalPort());

         // 服务器运行在本地,调用getLocalHost返回本地地址,此方法会抛出UnknownHostException

        serverAddress = InetAddress.getLocalHost();

       //2. 初始化向服务器端发送的数据包,包括 “数据包” 和“服务器地址端口” 两部分 

        //作用是服务器端接收包后获得客户端的地址和端口  

        outDataPacket = new DatagramPacket(msg, 1, serverAddress, serverPort);

        //3.发送数据包

        datagramSocket.send(outDataPacket);

        //4.初始化从服务器端传输过来的数据包.

        inDataPacket = new DatagramPacket(msg, msg.length);

        //5. 接收服务器端传输来的数据包

        datagramSocket.receive(inDataPacket);

        //6.转换byte[]成字符串:  byte[]   -> String

        String receivedMsg = new String(inDataPacket.getData(), 0, inDataPacket.getLength());

        System.out.println(receivedMsg);//打印消息

        //7.关闭socket

        datagramSocket.close();

    }

}

 4.Thread 线程  静态

    一个线程就是一个程序内部独立的流程控制序列代码

可以处理一系列指令的软件引擎

线程并发运行,相互独立

java.lang.Thread 包

线程的相关要素:

  Processor 处理器

  Code 代码

  Data 数据

 

 

Java 多线程机制

当启动一个线程时, 执行的是在 “public void run()”方法中的代码

创建java线程的两种方式:

   extending the classThread    继承Thread类

   implementing theinterface Runnable  实现Runnable接口

(1)通过继承Thread类定义线程类

Dinfining 定义

      public class MyThread extends Thread {

            public voidrun() {…}

      }

Instantiating 初始化

    MyThread testTthread =new MyThread()

构造函数:

   Thread()

   Thread(Runnable target)

方法

 run()

 start()

(2)通过扩展Runnable接口定义线程类

Difining 定义

      public classMyRunnable implements Runnable{

            public voidrun() {…}

      }

Instantiating实例化

    MyRunnable testRunnable= new MyRunnable();

    Thread testThread = newThread(testRunnable)

 执行run()方法中的代码

线程第一种实现方式  继承Thread 

package thread;

/**

 * 重写run方法

 * 类对象--线程对象 调用.start()启动线程

 */

public class Thread1 extends Thread {

    public Thread1(){}

    public Thread1(String name){

        super(name);

    }

    @Override

    public void run() {

        for(int i=0;i<500;i++){

            //System.out.println(this.getName()+"====="+i);     

            //获得当前线程实例Thread.currentThread()

System.out.println(Thread.currentThread().getName()+"====="+i);

        }

    }

   

   

    public static void main(String[] args) {

        Thread1 t1 = new Thread1("线程1");

        //t1.run();//线程对象.run()  不是多线程运行,而是普通的对象调方法

        t1.start();//启动线程方法 虚拟机调用该线程的 run 方法。

        for(int i=0;i<500;i++){

System.out.println(Thread.currentThread().getName()+"====="+i);

        }      

    }

}

线程第二种方式   实现Runnable接口

package thread;

/**

  实现run方法

 * 该类的实例r 只是Runnable实例 

 * 需要Threadt = new Thread(r);

 * t.start();启动线程    start方法会调用r对象的run()方法

 */

public class Thread2 implements Runnable {

    @Override

    public void run() {

        for(int i=0;i<500;i++){

            System.out.println("Thread====="+i);

        }

    }

    public static void main(String[] args) {

        //t并不是线程对象 只是Runnable实例

        Thread2 r = new Thread2();

        //r.run();

        Thread t = new Thread(r);

        t.start();//启动线程    start会调用run();

        for(int i=0;i<500;i++){

            System.out.println("main====="+i);

        }

    }

}

5.比较创建线程的两种方法

  通过继承Thread类是面向对象的编程思想

  扩展Runnable接口解决了单一继承的局限性

 

 

 

 

 

 

 

6.线程的状态转换图

 

 

 

 

 

 

 

 

 

 

 

 

 


终止一个线程

使用变量标签作为终止线程的指示符

Stop()方法已经被抛弃

静态方法Thread.currentThread()返回当前线程的一个引用

调试线程

判断线程的状态  isAlive()

线程的阻塞到运行

sleep()      Thread.sleep(5*1000)  休眠

中断一个线程  t.interrupt()

检查线程是否处于中断状态   otherThread.isInterrupted()

阻塞线程 otherThread.join()

实例:Sleep()

public class SleepTestThread extends Thread{

    @Override

    public void run() {

        while(true){

            Date d = new Date(); //获得当前时间

            System.out.println(d);

            try {

                Thread.sleep(1000);//休眠1

            } catch (InterruptedException e) {

                System.out.println("t线程sleep被打断");

                break;

            }

        }

    }

    public static void main(String[] args) {

        SleepTestThread t = new SleepTestThread();

        t.start();

        try {

            Thread.sleep(10000);//休眠10

            t.interrupt();//打断线程方法

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

    }

}

实例:Join()

public class JoinTestThread extends Thread {

    public JoinTestThread(Stringname){

        super(name);

    }

    @Override

    public void run() {

        for(int i=0;i<500;i++){

System.out.println(Thread.currentThread().getName()+"====="+i);

            try {

                Thread.sleep(10);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

    }

   

    public static void main(String[] args) {

        JoinTestThread t1 = new JoinTestThread("join线程1");

        t1.start();//启动线程方法 虚拟机调用该线程的 run 方法。

                for(int i=0;i<500;i++){

System.out.println(Thread.currentThread().getName()+"====="+i);

            if(i==100){

                try {

// t1加入(合并)到main线程中,并且main线程等待该线程t1终止,main再继续执行。

                    t1.join();

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

            }

        }

    }

}

实例:Yield()暂停当前正在执行的线程对象,并执行其他线程

      当调用yield()方法时,当前线程将会失去运行机会 Thread.yield()

public class YieldTestThread extends Thread{

    public YieldTestThread(Stringname){

        super(name);

    }

    @Override

    public void run() {

        for(int i=0;i<500;i++){

            System.out.println(this.getName()+"======"+i);

            if(i%10==0){

                //暂停当前正在执行的线程对象,并执行其他线程

                this.yield();

            }

        }

    }

    public static void main(String[] args) {

        YieldTestThread t1 = new YieldTestThread("线程1");

        YieldTestThread t2 = new YieldTestThread("线程2");

        t1.start();

        t2.start();

    }

}

Thread常用方法:

yield()  暂停当前正在执行的线程对象,并执行其他线程。

join() 等待该线程终止。

start()  使该线程开始执行;Java 虚拟机调用该线程的run 方法。

sleep(longmillis)在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)

setPriority(int newPriority) 更改线程的优先级。

getPriority()  返回线程的优先级。

setName(String name)  改变线程名称,使之与参数name 相同

getName() 返回该线程的名称。

getId()返回该线程的标识符。

run()  如果该线程是使用独立的Runnable运行对象构造的,则调用该Runnable 对象的 run方法;否则,该方法不执行任何操作并返回。

currentThread() 返回对当前正在执行的线程对象的引用。

 

 

 

考题:

1.java中有几种方法可以实现一个线程?

java5以前,有如下两种:

第一种:

new Thread(){}.start();这表示调用Thread子类对象的run方法,new Thread(){}表示一个Thread的匿名子类的实例对象,子类加上run方法后的代码如下:

new Thread(){

   public void run(){

   }

}.start();

 

第二种:

new Thread(new Runnable(){}).start();这表示调用Thread对象接受的Runnable对象的run方法,new Runnable(){}表示一个Runnable的匿名子类的实例对象,runnable的子类加上run方法后的代码如下:

new Thread(new Runnable(){

               public void run(){

               }    

        }

   ).start();

有两种实现方法,分别使用new Thread()new Thread(runnable)形式,第一种直接调用threadrun方法,所以,我们往往使用Thread子类,即new SubThread()。第二种调用runnablerun方法。

有两种实现方法,分别是继承Thread类与实现Runnable接口

2.sleep() wait() 有什么区别?

sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。

waitObject类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态

3.启动一个线程是用run()还是start()?

  启动一个线程是调用start()方法,使线程就绪状态,以后可以被调度为运行状态,一个线程必须关联一些具体的执行代码,run()方法是该线程所关联的执行代码。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2011.8.11                     周四

1.线程的优先级:

  设置线程的优先级 setPrioirity(int)

  使用优先级和让步调度线程

Public final void setPriority(int newPriority)  更改线程的优先级(级别从1-10)

Public static final int  MAX_PRIORITY10; 线程可以具有的最高优先级。

Public static final int  MIN_PRIORITY 1;  线程可以具有的最低优先级。

Public static final int  NORM_PRIORITY5;  分配给线程的默认优先级。
2.线程同步存取问题  并发操作  同步就是给类类型对象加锁的过程

多个线程经常在某种程度上存在信息的共享

无法保证两行代码在处理器中一个接一个的执行

Java使用同步机制控制同步存取问题

关键字synchronized标记一组在线程中相互之间互斥的的变量

同步方法 synchronized void methodA() {…}

同步代码void methodA() {

                  synchronized(this) {…}}

voidmethodB() {

                  //Object obj = new Object();

                   synchronized(obj) {…}

synchronized(互斥锁)线程同步 在java中,为保证共享数据操作的完整性,每个对象都对应于一个称为互斥锁的标记,这个标记保证在任一时刻只能有一个线程访问该对象。关键字synchronized来与对象的互斥锁联系。当某个对象synchronized修饰时,表明该对象在任一时刻只能有一个线程访问
两种方式实现同步:

1. synchronized (this){代码}方法内同步代码区用synchronized(this)包括

synchronized (Object共享资源对象){

            只能一个线程执行

        }

2.synchronized void add(String name){代码}   方法前用synchronized修饰

实例:

public class ThreadSynchronizedTest implements Runnable {

    Timer t = new Timer();

    public void run() {

        t.add(Thread.currentThread().getName());

    }

 

    public static void main(String[] args) {

        ThreadSynchronizedTesttest = new ThreadSynchronizedTest();

        Thread t1 = new Thread(test);

        Thread t2 = new Thread(test);

        t1.setName("thread1");

        t2.setName("thread2");

        t1.start();

        t2.start();

    }

}

class Timer{

    Object o = new Object();

    private static int num =0;

    //public void add(String name){   第二种

    public synchronized void add(String name){

    //synchronized (o){  (互斥锁)锁定当前对象 一个线程开始后,执行过程中不会有另一个线程进入

        //synchronized (this){  第一种

            num++;

            try {

                Thread.sleep(1);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        System.out.println(name+",你是第 "+num+"个使用Timer的线程!");

        //}

    }

}

重点:找到共享资源

3.Wait()、Notify()、NotifyAll() 都在Object类中

  wait() 在其他线程调用此对象的 notify() 方法或notifyAll() 方法前,导致当前线程等待。

  notifyAll() 唤醒在此对象监视器上等待的所有线程。

  notify()唤醒在此对象监视器上等待的单个线程。

通过等待和唤醒交互

通过信号系统来保证线程之间的恰当的执行顺序

两个独立的线程使用wait() 和notify()方法

当有许多线程处于等待状态时,使用notifyAll()

实例:栈的模拟

 public class MyStack {

    //模拟栈指针   index值指向顶端元素的上一个位置     压栈索引

    private int index=0;

    //数组  存放栈数据

    private int [] s = newint[10];

    //GetSet方法

    public int[] getS() {

        return s;

    }

    public void setS(int[] s) {

        this.s = s;

    }

    /**

     * 压栈方法

     */

    public synchronized void push(int i){

        if(index==s.length){//满了

            System.out.println("栈满了,请等待弹栈操作.....");

            try {

                wait();//线程等待   等待其他线程唤醒自己

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }  

        s[index] = i;//压栈

        index++;//指针上移

        System.out.println("压栈执行.......压入元素:"+i);

        notify();//唤醒其他等待线程  

    }

    /**

     * 弹栈方法

     */

    public synchronized int pop(){

        int result = 0;

        if(index==0){//空了

            System.out.println("栈空了,请等待压栈操作........");

            try {

                wait();//等待其他线程唤醒自己

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

        index--;

        result = s[index];

        System.out.println("弹栈执行.......弹出元素:"+result);

        notify();//唤醒其他等待线程

        return result;

    }

}

压栈线程:

public class SynPushThread extends Thread {

    MyStack stack;

    public SynPushThread(MyStackstack) {

        super();

        this.stack = stack;

    }

    @Override

    public void run() {

        for(int i=0;i<30;i++){

            stack.push(i);

        }

    }

}

弹栈线程:

public class SynPopThread extends Thread {

    MyStack stack;

    public SynPopThread(MyStackstack) {

        super();

        this.stack = stack;

    }

    @Override

    public void run() {

        for(int i=0;i<30;i++){

            stack.pop();

        }

    }

}

线程测试类:

public class MyStackTest {

    public static void main(String[] args) {

        MyStack stack = new MyStack();

        SynPushThread pushThread= new SynPushThread(stack);

        SynPopThread popThread =new SynPopThread(stack);

        pushThread.start();

        popThread.start();

    }

}

4.死锁:线程都在资源上互相等待

线程的饿死或死锁环境

 实例:

public class DeadLockTest implements Runnable{

      protected  Resource resA, resB;

      public DeadLockTest(Resource r1, Resource r2) {

        resA=r1;

        resB=r2;

      }

      public void run() {  // called by t thread      

             write(38,36);   //call write()         

      }

     

      // called by run methodof t thread

public void write(int num1,int num2)  {                                synchronized(resA){

            try {

              System.out.println(" write thread");

              Thread.sleep(10);

            }catch(Exception e){

              e.printStackTrace();

            }

            synchronized(resB){

                resA.number=num1;

                resB.number=num2;

        System.out.println(" Resource A, number is: " +resA.number);

        System.out.println("  Resource B, numberis: " +resB.number );

            }

         }

      }

      public  int read()  {  // called by main thread

             synchronized(resB){

              try {

                 System.out.println(" read thread");

                 Thread.sleep(10);

              }catch(Exception e){

               e.printStackTrace();

             }

             synchronized(resA){

                int totalNum=resA.number+resB.number;

 System.out.println(" Resource  A and B, total number " + totalNum);

                return totalNum; 

            }    

        }

      }

      public static void main(String[] args) {   

DeadLockTest q=new DeadLockTest(new Resource(20),new Resource(30)); 

         Thread t=new Thread(q);

         t.start();          //start t Thread, callrun method

         q.read();           //  called by main thread             

      }

    }

    class Resource{

       int number;

       public Resource(int num){

            number=num;

        }

    }

5.线程分两大类:  用户线程   守护线程

 * 用户线程:isDaemon--->false  正常应用的大部分都是用户线程

 * 守护线程:将用户线程(普通线程).setDaemon(true),线程就是守护线程

          守护线程运行在后台,专门服务前台用户线程,如果前台没有任何用户

          线程在运行,守护线程会自动终止。

          比如 垃圾回收的线程就是守护线程,当类执行完(所有的用户线程执行完),

          JVM 结束,垃圾回收的守护线程也会自动结束

 * 开发守护线程和用户线程没有任何区别,只需要创建线程对象后,执行setDaemon(true)就将用户线程设置为守护线程。

 * 注意:守护线程的设置setDaemon(true) 一定要在线程start()之前

public class DaemonThread extends Thread {

    @Override

    public void run() {

        for(int i=0;i<100;i++){

            System.out.print(this.getName()+"===="+i);

            if(this.isDaemon()){//判断是否为守护线程

                System.out.println("该线程是守护线程");

            }else{

                System.out.println("该线程是用户线程");

            }

            try {

                Thread.sleep(1);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

    }

    public static void main(String[] args) {

        DaemonThread t = new DaemonThread();

        t.setName("线程1");

        t.setDaemon(true);//在线程启动前设置  为守护线程

        t.start();

        for(int i=0;i<100;i++){

            System.out.println("main====="+i);

        }

    }

}

 

考题:

     一个线程的run() 方法包含以下几行:

      1. try{

      2.    sleep(100);

      3. }catch(InterruptedException e) {}

假设线程没有被打断,下面的陈述哪个正确?(D

  A.代码不会被编译,因为run()方法中的异常不能被捕获.

  B.线程将会停止在第二行,最多一百毫秒后就会继续执行。

  C. 线程将会停止在第二行,一百毫秒后就会继续执行

  D. 线程将会停止在第二行,一百毫秒后的某个时间恢复执行

2.一个线程想使第二个当前没有执行权的线程执行,那么第一个线程可以通过对第二个线程调用yield()方法来实现吗?(B

     A. True              B. False

3.下列代码向 一个文件中写入了多少个字节?(C

    1. try{

    2.    FileOutputStream fos = newFileOutputStream(“dest”);

    3.    DataOutputStream dos = newDataOutputStream(fos);

    4.    dos.writeInt(3); 4个字节

    5.    dos.writeDouble(0.001);  8个字节

    6.    dos.close();

    7.    fos.close();

    8.  } catch(IOException e) {}

        A. 2          B. 8           C. 12         D. 16

 

4.用什么关键字修饰同步方法? stop()suspend()方法为何不推荐使用?

   synchronized关键字修饰同步方法

       反对使用stop(),是因为它不安全。它会解除由线程获取的所有锁定,而且如果对象处于一种不连贯状态,那么其他线程能在那种状态下检查和修改它们。结果很难检查出真正的问题所在。

       suspend()方法容易发生死锁。调用suspend()的时候,目标线程会停下来,但却仍然持有在这之前获得的锁定。此时,其他任何线程都不能访问锁定的资源,除非被"挂起"的线程恢复运行。对任何线程来说,如果它们想恢复目标线程,同时又试图使用任何一个锁定的资源,就会造成死锁。

      所以不应该使用suspend(),而应在自己的Thread类中置入一个标志,指出线程应该活动还是挂起。若标志指出线程应该挂起,便用wait()命其进入等待状态。若标志指出线程应当恢复,则用一个notify()重新启动线程。

5.多线程有几种实现方法?同步有几种实现方法?

多线程有两种实现方法,分别是继承Thread与实现Runnable接口

同步的实现方面有两种,分别是synchronized,waitnotify

 wait():使一个线程处于等待状态,并且释放所持有的对象的lock

 sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException异常。

 notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。

Allnotity():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。

6.当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?

   分几种情况:

     1.其他方法前是否加了synchronized关键字,如果没加,则能。

     2.如果这个方法内部调用了wait,则可以进入其他synchronized方法。

     3.如果其他个方法都加了synchronized关键字,并且内部没有调用wait,则不能。

        4.如果其他方法是static,它用的同步锁是当前类的字节码,与非静态的方法不能同步,因为非静态的方法用的是this

 

 

原创粉丝点击