程序:是为完成特定任务,用某种语言编写的一组指令的集合,即指一段静态的代码,静态对象 进程:是程序的一次执行过程,或是正在运行的一个程序,是一个动态的过程,有它自身的产生,存在和消亡的过程——生命周期。进程作为资源分配的单位,系统在运行时会为每个进程分配不同的内存区域 线程:进程可进一步细化为线程,是一个程序内部的一条执行路径,若一个进程同时并行执行多个线程,就是支持多线程的,线程作为调度和执行的单位,每个线程拥有独立的运行栈和程序计数器(pc) 一个java应用程序java.exe,至少有三个线程:main()主线程,gc()垃圾回收线程,异常处理线程,当然如果发生异常,会影响主线程
并行与并发: 并行:多个cpu同时执行多个任务,比如多个人同时做不同的事 并发:一个cpu同时执行多个任务,比如多个人同时做同一件事。
多线程的创建:方式一:继承于Thread类 1.创建一个继承于Thread类的子类 2.重写Thread类的run()-->将此线程执行的操作声明在run()中 3.创建Thread类的子类的对象 4.通过此对象调用start():启动当前线程,并调用当前线程的run() 问题一:不能通过直接调用run()方法启动线程 问题二:再启动一个线程,不可以还让已经启动start()的线程去执行,会报错 ?? ?我们需要重新创建一个线程对象(new MyThread()) class MyThread extends Thread{ ? ? @Override ? ? public void run() { ? ? ? ? for (int i = 0; i < 100; i++) { ? ? ? ? ? ? if (i%2==0){ ? ? ? ? ? ? ? ? System.out.println(i); ? ? ? ? ? ? } ? ? ? ? } ? ? } } public class ThreadTest{ ? ? public static void main(String[] args) { ? ? ? ? MyThread myThread = new MyThread(); ? ? ? ? myThread.start(); ? ? ? ? System.out.println("hello"); ? ? } }
方式二:实现Runnable接口 1.创建一个实现了Runnable接口的类 2.实现类去实现Runnable中的抽象方法:run() 3.创建实现类的对象 4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象 5.通过Thread类的对象调用start()
比较创建线程两种方式: 开发中优先选择实现Runnable接口的方式 原因:1.实现的方式没有类的单继承性的局限性 ? ? ? ? ? 2.实现的方式更适合用来处理多个线程有共享数据的情况 联系:public class Thread implements Runnable 相同点:两种方式都需要重写run(),将线程要执行的逻辑声明在run()中
测试Thread中的常用方法 1.start():启动当前线程,调用当前线程的run() 2.run():通常需要重写Thread类中的此方法,将创建的线程要执行的操作声明在此方法中 3.currentThread():静态方法,返回执行当前代码的线程 4.getName():获取当前线程的名字 5.setName():设置当前线程的名字 6.yield():释放当前cpu的执行权(有可能在下一刻cpu又分配到当前线程) 7.join():在线程a中调用线程b的join(),此时线程a就进入阻塞状态,直到线程b完全执行后,线程a才结束阻塞状态。 8.stop():已过时,当执行此方法时,强制结束当前线程 9.sleep(long millitime):让当前线程“睡眠”指定的millitime毫秒,在指定的millitime毫秒时间内,当前线程是阻塞状态。 10.isAlive():判断当前线程是否存活
线程的优先级: 1.MAX_PRIORITY:10 提高被线程优先执行的概率,不意味着只有高优先级线程执行完,低优先级才执行 ? MIN_PRIORITY:1 ? NORM_PRIORITY:5 2.如何获取设置当前线程优先级: getPriority():获取优先级 setPriority():设置优先级
线程的五种状态: 新建,就绪(已经具备运行条件,还没分到cpu资源),运行,阻塞,死亡 就绪-->获取cpu执行权-->运行-->失去cpu执行权 或 yield()-->就绪
使用同步方法解决实现Runnable接口的线程安全问题:如果操作共享数据的代码完整的声明在一个方法中,我们不妨将此方法声明同步的 1.同步方法仍然涉及到同步监视器,只是不需要我们显示的声明 2.非静态的同步方法,同步监视器:this ? ?静态的同步方法,同步监视器是:当前类本身
解决线程安全问题方式三:Lock锁 private ReentrantLock lock = new ReentrantLock(true)//实例化对象 lock.lock(); lock.unlock(); 面试题:synchronized 与 lock的异同: ?? ?相同:二者都可以解决线程安全问题 ?? ?不同:synchronized机制在执行完相应的同步代码后,自动释放同步监视器 ?? ? ? ? ? ? ?lock需要手动的启动同步,结束同步也需要手动的实现 优先使用顺序:lock->同步代码块->同步方法
线程通信的例子:使用两个线程打印1-100,线程1,线程2交替打印 涉及到的三个方法: wait():执行此方法,当前线程就进入阻塞状态,并释放同步监视器 notify():执行此方法,,就会唤醒被wait的一个线程,如果有多个线程被wait,就唤醒优先级高的 notifyAll():执行此方法,会唤醒所有被wait的线程。 说明:1.三个方法必须使用在同步代码块或同步方法中 ? ? ? ? ? 2.三个方法的调用者必须是同步代码块或同步方法中的同步监视器,否则会出现异常。 ? ? ? ? ? 3.三个方法是定义在java.lang.Object类中 面试题:sleep()和wait()的异同? 1.相同点:一旦执行方法,都可以使得当前的线程进入阻塞状态 2.不同点:声明位置不同:Thread类中声明sleep(),Object类中声明wait() ?? ?调用要求不同:sleep()可以在任何需求的场景下调用。wait()必须使用在同步代码块中 ?? ?如果两个方法都使用在同步代码块中sleep()不释放同步监视器,wait()释放
创建线程方式三:实现Callable接口 Callable接口的方式创建多线程比实现Runnable接口创建多线程方式强大 1.call()可以有返回值 2.call()可以抛出异常,被外面的操作捕获,获取异常信息 3.Callable支持泛型。
创建线程方式四:使用线程池,开发中常用 思路:提前创建好多个线程,放入线程池中,使用时直接获取,使用完返回池中,可以避免频繁创建销毁,实现重复利用, 好处:提高响应速度,降低资源消耗,便于线程管理 1.提供指定线程数量的线程池 ExecutorService service = Executor.newFixedThreadPool(nThreads:10); 2.执行指定的线程的操作,需要提供实现Runnable接口或Callable接口实现类的对象 service.execute(new NumberThread());//适用于Runnable service.submit(Callable callable);//适用于Callable 3.关闭连接池 service.shutdown();
java io 用于处理设备之间的数据传输,以流(stream)的方式进行 FileReader读入数据: 将文件内容读入程序中: 1.实例化File类对象,指明要操作的文件 File file = new File("hello.txt"); 2.提供具体的流 FileReader fr = new FileReader(file); 3.数据的读入//read()返回读入的一个字符,如果达到文件末尾,返回-1 int data = fr.read(); while(data!=-1){ ?? ?sout((char)data); ?? ?data = fr.read();} 使用read()的重载方法,read(char[] cbuf):返回每次读入cbuf数组中的字符的个数,如果达到文件末尾返回-1 char[] cbuf = new char[5]; int len; while((len = fr.read(cbuf))!=-1){ ?? ?for(int i ?=0;i<len;i++){ ?? ??? ?sout(cbuf[j]);}} //错误的写法:for(int i = 0;i<cbuf.length;i++)?? ?char读入数据时是覆盖操作 4.流的关闭操作 fr.close();
FileWriter从内存中写出数据到硬盘的文件中: 说明:1.输出操作对应文件可以不存在,在输出过程中会自动创建该文件 2.如果存在:如果流使用构造器是FileWriter(file,false)/FileWriter(file):对原有文件的覆盖;FileWriter(file,true):在原有文件后接着写出 File file = new File("hello1.txt"); FileWriter fw = new FileWriter(file); fw.write("\n"); fw.close();
使用filereader和filewriter实现文本文件复制 File srcFile = new File(); File destFile = new File(); fr.FileReader(); fw.FileWriter(); char[] cbuf = new char[5]; int len; while((len = fr.read(cbuf))!=-1){ ?? ?fw.write(cbuf,0,len);}//每次写出Len个字符 fw.close();fr.close();
结论: 1.对于文本文件(.txt,.java,.c,.cpp),使用字符流处理 2.对于非文本文件(.jpg,.mp3,.mp4,.avi,.doc,.ppt,...),使用字节流处理
处理流之一:缓冲流的使用 1.BufferedInputStream,bufferedoutputstream,bufferedreader,bufferedwriter 2.作用:提供流的读取,写入的速度?? ?提高读写速度原因:内部提供了一个缓冲区 实现非文本文件的复制: 1.造文件 File srcFile = new File(); File destFile = new File(); 2.1造节点流 FileInputStream fis = new FileInputStream(srcFile); FileOutputStream fos = new FileOutputStream(destFile); 2.2造缓冲流 BufferedInputStream bis = new BufferedInputStream(fis); BufferedOutputStream bos = new BufferedOutputStream(fos); 3.复制的细节:读取,写入 byte[] buffer = new byte[10]; int len; while((len = bis.read(buffer))!=-1){ ?? ?bos.write(buffer,0,len)} 4.资源关闭:关闭外层流的同时,内层流也会自动关闭,关于内层流关闭,我们可以省略 bis.close(); bos.close();
处理流之二:转换流的使用: 1.转换流:属于字符流 InputStreamReader:将一个字节输入流转换为字符输入流 OutputStreamWriter:将一个字符输出流转换为字节输出流 2.作用:提供字节流与字符流之间的转换 3.解码:字节,字节数组->字符数组,字符串 编码:字符数组,字符串->字节,字节数组 4.字符集 将字节流转字符流: FileInputStream fis = new FileInputStream(); InputStreamReader isr = new InputStreamReader(fis,"utf-8")//具体使用哪个字符集,取决于文件使用哪个字符集
System.in:标准的输入流,默认从键盘输入 System.on:标准的输出流,默认从控制台输出//都为字节流 InputStreamReader isr = new InputStreamReader(System.in); br = new BufferedReader(isr);
网络编程的目的:直接或间接的通过网络协议与其他计算机实现数据交换,进行通讯 网络编程中两个主要问题:1.如何准确定位主机2.如何进行可靠高效的数据传输 网络编程中两个要素:1.对应问题1 ip号和端口号 2.对应问题2 提供网络通信协议:TCP/IP参考模型 通信要素一:IP和端口号 1.IP:唯一的标识Internet上的计算机 2.在java中使用InetAddress类代表IP 3.IP分类:IPv4和IPv6;万维网和局域网 4.域名: 5.本地回路地址:127.0.0.1 ?对应着localhost 6.如何实例化InetAddress:两个方法:getByName(String host),getLocalHost(); 两个常用方法:getHostName()/getHostAddress() 7.端口号标识正在计算机上运行的进程,不同的进程有不同的端口号,范围:0~65535 8.端口号与IP地址的组合得出一个网络套接字:Socket
TCP协议网络编程:例子1:客户端发送信息给服务端,服务端将数据显示在控制台上 客户端: 1.创建socket对象,指明服务器端的ip和端口号 InetAddress inet = InetAddress.getByName("192.168.14.100") Socket socket = new Socket(inet,8899) 2.获取一个输出流,用于输出数据 OutputStream os = socket.getOutputStream(); 3.写出数据的操作 os.wrute("nihao".getBytes()); 4.资源的关闭 os.close(); socket.close(); 服务端: 1.创建服务器端的ServerSocket,指明自己端口号 ServerSocket ss = new ServerSocket(8899); 2.调用accept()表示接收来自于客户端的socket Socket socket = ss.accept(); 3.获取输入流 InputStream is = socket.getInputStream(); 4.读取输入流中的数据 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 5.资源关闭
|