黑马程序员——包、多线程

来源:互联网 发布:华为 知乎 编辑:程序博客网 时间:2024/05/17 21:07
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


一.
  1. 对类文件进行管理

  2. 给类提供多层命名空间

  3. 写在程序的第一行

  4. 类名全称是:包名.类名

  5. 包也是一种封装形式

     

    1、包与包之间访问

1)包与包(类与类)不在同一目录时,需要设置classpath变量,告诉jvm去哪里找指定的包。

2)被访问的类要被public修饰。一个包中的类要被访问,必须要有足够大的权限。类公有后,被访问的成员也要公有才可以被访问。

3)包与包之间进行访问,被访问的包中的类以及类中的成员,需要public修饰。

(因为一个包中的类要被访问,必须要有足够大的权限。)

4)不同包中的子类还可以直接访问父类中被protected权限修饰的成员。

5)包与包之间可以使用的权限只有两种,publicprotected

6)不同修饰符可以修饰哪些内容

 

 

2import关键字

 

为了简化类名的书写,使用一个关键字,import.

import导入的是包中的类。

建议,不要写通配符*,在此代表所有类,需要用到包中的哪个类,就导入哪个类。节省内存空间。

注意:当导入的不同包中含同名类,创建对象时,不允许简写,类名前必须写相应包名。

Java不允许用户在声明包时使用java作为包名的第一部分。例如:java.pkg是非法的。

 

一个程序文件中只有一个package,可以有多个import

用来导包中的类,不导入包中的包。

通常写import mypack.Demo,明确自己使用的类。

关键字的顺序

类,包,导包这些关键字的顺序。

--> 导包-->

 

二.JAVA多线程

  1. A、线程概述

    进程:正在进行中的程序(直译);

    线程:就是进程中一个负责程序执行的控制单元(执行路径)

    一个进程中可以有多个执行路径,称之为多线程。

    一个进程中至少要有一个线程。

    开启多个线程是为了同时运行多部分代码。

    每一个线程都有自己运行的内容。这个内容可以称为线程要执行的任务。

     

    多线程的弊端:线程太多会导致效率降低。

     

    JVM启动时就启动了多个线程,至少有两个线程可以分析出来。

  1. 执行main函数的线程。

    该线程的任务代码都定义在main函数中。

  2. 负责垃圾回收的线程。

     

    B、如何创建一个线程呢?

           创建线程方式一:继承Thread类。

    步骤:1、定义一个类继承Thread类。

             2、覆盖Thread类中的run方法。

             3、直接创建Thread的子类对象创建线程。

             4、调用start方法开启线程并调用线程的任务run方法的执行。

     

           创建线程方式二:实现Runnable接口

  1. 定义类实现Runnable接口。

  2. 覆盖接口中的run方法,将线程的任务代码封装到run方法中。

  3. 通过Thread类创建线程对象,并将Runnable接口的子类对象作为Thread类的构造函数的参数进行传递。因为线程的任务都封装在Runnable接口子类对象的run方法中。所以要在线程对象创建时就必须明确要运行的任务。

  4. 调用线程对象的start方法开启线程。

     

    实现Runnable接口的好处:

  1. 将线程的任务从线程的子类中分离出来,进行了单独的封装。按照面向对象的思想将任务封装成对象。

  2. 避免了JAVA单继承的局限性。

    所以创建线程的第二种方式较为常用。

     

    创建线程的目的是为了开启一条执行路径,去运行指定的代码和其它代码实现同时运行。而运行的指定代码就是这个执行路径的任务。

    JVM创建的主线程的任务都定义在了主函数中。

     

    而自定义的线程在哪呢?

    Thread类用于描述线程,线程是需要任务的。所以Thread类也对任务的描述。这个任务就通过Thread类中的run方法来体现,也就是说,run方法就是封装自定义线程运行任务的函数。

     

    开启线程是为了运行指定代码,所以只有继承Thread类,并复写run方法。将运行的代码定义在 run方法中即可。

     

    调用run和调用start有什么区别

    调用run相当于函数调用了一个run方法,其线程并未启动。

    调用start相当于让JVM虚拟机开辟一个线程来调用run方法,这时候多线程才真正被启动。

     

    可以通过ThreadgetName获取线程的名称。Thread-编号(从0开始编)



一、线程的四种状态:



 


CPU的执行资格:可以被CPU处理,在处理队列中排除。


CPU的执行权:正在被CPU处理。


 


线程安全问题产生的原因:


  1. 多个线程在操作共享的数据。

  2. 操作共享数据的线程代码有多条。

    当一个线程在执行操作共享数据的多条代码过程中,其它线程参与运算。就会导致线程安全问题的产生。

     

    解决思路:就是将多条操作共享数据的线程代码封装起来,当有线程在执行这些代码的时候,其它线程是不可以参与运算的。必须要当前线程把这些代码都执行完毕后,其它线程才可以参与运算。

     

    JAVA中,用同步代码块就可以解决这个问题。

    同步代码块的格式:synchronized(对象){需要被同步的代码;}

    理解:对象如同锁,持有锁的线程可以在同步中执行。没有持有锁的线程即使获取CPU执行权,也进不去,因为没有获取锁。

     


注意:同步的前提:必须要有两个或者两个以上的线程。


必须是多个线程使用同一个锁。


必须保证同步中只能有一个线程在运行。


同步优点:解决了多线程的安全问题。


同步弊端:多个线程需要判断锁,较为消耗资源。


在多线程操作共享数据的运行代码中,需要加锁的两种情况:


1、含有选择判断语句


2、含try(){}catch(){}语句


 


二、多线程同步函数


      同步代码块与函数都是封装代码,有什么区别?


同步代码块具有同步的特性。


同步函数:使函数具备同步功能。需将同步放在函数修饰符上


即:public synchronized返回值类型函数名(形参){}


例如: public synchronized void add(){  //功能执行语句


函数需要被对象调用,那么函数都有一个所属对象引用this。因此,同步函数所使用的锁是this


建议使用同步代码块,因为同步函数所持有的锁是唯一的,就是this4


三、静态同步函数


同步函数被静态修饰后,通过验证,发现锁不再是this,因为静态方法中不可以定义this。静态进内存时,内存中没有本类对象,但一定有该类对应的字节码文件对象。类名.class该对象的类型是class


静态的同步方法,使用的锁是该方法所在类的字节码文件对象。类名.class


this.getClass();可以获取当前类对象的字节码文件对象。


      


      死锁:同步中嵌套同步。


 


      线程间的通信其实就是多个线程在操作同一资源,但操作的动作不同。



 

Thread.currentThread().getName()获取当前线程名字。------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------



0 0