java基础(三)

Date对象
        Date类的方法
            ·构造方法:
                -public Date()
                -public Date(Long date)传递一个long类型的参数
            ·获取时间:
                -public long getTime()以long类型返回
            long cur=System.currentTimeMillis();//获取从1970年1月1日到当前的毫秒数    
        日期格式化对象(SimpleDateFormat)            
            ·构造方法:
                -public SimpleDateFormat(String pattern)//参数是我们需要的格式"YYYY-MM-DD HH:mm:ss.SSS"
            ·格式转换:
                -public final String format(Date date)//将Date类型转变成String类型日期
                -public Date parse(String sourse)//将String类型日期转变成Date类型
                sdf.setLenient(false);//开启严格模式
泛型
     泛型<T>通配符?有两个子通配符分别是?extends类,?super类
         ?extends类:可以用于类的泛型,也可以用于方法的泛型;是设置范型的上限,一旦为类设置范型上限,那么实例化
             子类的时候只能是泛型上限所对应的类或者子类 fun(Message<?extends Object> msg);                
         ?super 类:只能用于方法参数的泛型,能接受的参数的泛型只能是该类或者该类的父类 fun(Message<?super integer> msg);
     新泛型
         如果要定义一个方法可以接受任意个数的参数,这里就可以用新泛型来实现public static <T>T[] fun(T...temp)
         {return temp;}    
异常
    Eorr和Exception都是Throwable的子类
    Eorr:是程序还没有运行之前就出现的错误,是JVM出现的错误是不能通过捕获处理的
    Exception:是程序在运行中出现的异常,是可以通过捕获处理的。
    程序出现了异常JVM会自动实例化一个对应的异常对象,再判断是否存在异常的捕获语句    throws关键字放到方法名后面,一旦方法中使      用了关键字,那么在该方法中出现的异常,将会向上抛出,交给调用处去处理该异常。
    throw关键字位置是在方法体中,手动抛出异常。
    Exception是异常要求强制处理的,RuntimeException不要求强制性处理,可以选择性的处理
断言
    assert关键字是在jdk1.4版本引入的表示断言
    assert num==20; (num的值是20)
线程与进程
    进程是线程的载体,一个进程由多个线程组成,线程要依附于线程,一旦进程关闭,那么线程就不存在了。
    系统要区分线程是通过线程的名字来区分的,那么如何设置和获取线程的名字呢?
        -public final String getName()获取线程的名字
        -public final void setName(String name)设置线程的名字
        -public Thread(Runnable target,String name)初始化线程,并设置名字
        -Thread.currentThread().getName() 获取正在运行的线程的名字
    在使用Java命令运行一个Java程序时,JVM会启动一个进程,这个进程至少就会启动两个线程
        -主方法是一个线程
        -GC垃圾回收线程    
线程的休眠
    Thread.sleep(毫秒数);    
线程的优先级
    线程有三种优先级,原理上是优先级越高那么线程就越先执行,但这仅仅是可能是不一定 
        ·高优先级:public static final int MAX_PRIORITY=10
        ·中等优先级:public static final int NORM_PRIORITY=5
        ·最低优先级:public static final int MIN_PRIORITY=1        
            -设置优先级    public final void setPriority(int newPriority)
            -获取优先级 public final int getPriority
多线程的实现
    要实现线程,在JDK1.5之前有两种方式
        ·继承Thread类,Thread类是一个支持线程操作的类,只要是该类的子类都可以实现多线    程的所有操作
        ·实现Runnable接口
    在JDK1.5之后提供了Callable接口也可以实现线程的操作,但是目前在开发中一般使用前面    两种
    一个Java程序的起点是main方法(其实也叫主线程),在main方法中启动的其他线程叫做之子线程,理所当然它们也有自己的起点方法,这个起点方法就是run方法,run()需要覆写,在启动之后并没有体现多线程的并发性,而是有序的,根本原因是使用run()启动线程的,
    所以在启动线程的时候要使用start()方法。
start()方法
    start()方法在启动时调用start0()方法,该方法没有方法体,类似于一个抽象方法,使用 native,在Java的开发中有一种技术叫  做JNI(Java Native Interface)技术,该技术是使用Java程序调用本地操作系统的函数,我们在启动线程的时候,操作系统必须为每一个线程分配资源,那么在分配的时候由于操作系统的支持性不同,所以每一种操作系统分配资源方式不一样,那么start0()方法就不能写死,只能定义出一个标准,具体分配实现方式有JVM根据操作系统的不同实现不同的分配方式,这也是表现Java的可移植性的表现之一。
    要启动多线程就必须使用start()方法,start()方法中调用start0()完成资源的分配    之后系统再自动调用run()方法。
Runnable接口
    在Runnable接口中并没有start()方法,但是在Thread构造方法中,我们可以将Runnable接口作为参数传递过去。public Thread (Runnable target){}
    继承Thread:这种方式有单继承的局限,而且不能方便的实现线程之间的数据共享
    实现Runnable接口:没有单继承的局限,而且能方便的实现数据之间的共享,实现多线程,使用实现Runnable接口的方式是最好的。
线程的同步
    如果线程不同步,那么多个线程访问统一数据的时候就会出现风险
        -使用同步代码块
            语法:synchronized(this){...}
        -使用同步方法
            语法 public synchronized void run(){...}
    同步的负面效应
        ·使用同步,那么代码的执行效率就会降低,因为当前线程要等待上一个线程执行完毕之    后才能执行。        
        ·使用同步,有时候会出现死锁现象(但是这个概率非常小)
多线程的生产者,消费者模式

class PublicBox { 
    //产品 
private int apple = 0;     
    public synchronized void increace() { 
        while (apple ==5) { 
        try { 
            wait(); 
            } catch (InterruptedException e) { 
            e.printStackTrace(); 
            } 
           
        } 
        apple++; 
        System. out .println("生成苹果成功!" );
        notify(); 
    }
    public synchronized void decreace() { 
     while (apple ==0) { 
         try { 
             wait(); 
             } catch (InterruptedException e) { 
                 e.printStackTrace(); 
             } 
         } 
         apple--; 
         System. out.println( "消费苹果成功!" );
         notify(); 
     } 
  }  
class Producer implements Runnable { 
                //生产者 
private PublicBox box; 
public Producer(PublicBox box) { 
this .box = box; 
} 
@Override 
public void run() { 
for( int i=0;i<10;i++){
       try {
             System. out .println("pro  i:" +i);
                   Thread. sleep(30);
             } catch (InterruptedException e) {
                   e.printStackTrace();
             }
    box.increace(); 
}
 
} 
}
 class Consumer implements Runnable { 
                //消费者 
private PublicBox box; 
public Consumer(PublicBox box) { 
this .box = box; 
} 
@Override 
public void run() { 
for( int i=0;i<10;i++){
     try {
             System. out .println("Con: i " +i);
                   Thread. sleep(30);                  
             } catch (InterruptedException e) {
                   
                   e.printStackTrace();
             }
    box.decreace(); 
} 
} 
 }
public class Test{
public static void main(String []args) {
             PublicBox box= new PublicBox();
             
             Consumer con= new Consumer(box);
             Producer pro= new Producer(box);
             
             Thread t1= new Thread(con);
             Thread t2= new Thread(pro);
             
             t1.start();
             t2.start();
             
             
      }
}

 

当一个线程访问一个对象的同步方法的时候,如果该线程进入方法之后使用sleep方式休眠,那么在休眠期间其他任何线程不能访问该对象的任何同步方法,也就是说sleep在休眠的时候是不会释放锁的。

当一个线程进入一个对象的同步方法之后使用wait方式休眠的情况下,在休眠的期间,其他线程可以访问该对象的所有同部方法,也就说使用wait方法休眠的线程可以释放锁  

·sleep:

|-sleep()是Thread的方法

|-使用sleep休眠的线程会自动醒来

|-使用sleep休眠的线程不会释放锁

·wait():

|-wait()是Obejct类中的方法

|-使用wait休眠的线程需要使用notify或者notifyAll方法唤醒

|-使用wait休眠的线程会释放锁。 

请分析一下代码输出“A”和“B”各多少次? 

 

class Productor implements Runnable{
    @Override
    public void run() {
         for(int i=0;i<50;i++){
          try {
            Thread.sleep(300);
          } catch (InterruptedException e) {
             e.printStackTrace();
           }
             System.out.println("A");
         }
        }
}
class Customer implements Runnable{
@Override
    public void run() {
        for(int i=0;i<50;i++){
          System.out.println("B");
            }   
        }
}
 public class Test {
    public static void main(String[] args) throws Exception {
        Thread th1=new Thread(new Productor()) ;
        Thread th2=new Thread(new Customer()) ;
        th1.setDaemon(true);//及A设置为守护线程
        th1.start();
        th2.start();
    }
}

 

  

 

答:以上代码输出“A”是不确定, 输出“B”是50次

 原因是输出A的线程是守护线程,B的线程是非守护线程(用户线程)

守护线程为非守护线程而服务,所以当JVM中如果没有非守护线程的时候,所有的守护线程都会结束,
就算守护线程中的run()方法中的代码还没执行完毕也会被强制结束。但是非守护线程一定会执行完毕, 

以上的代码A是由守护线程输出,B是由非守护线程输出,所以A的次数是不定的,B的次数是50固定的 

我们最常见的典型的守护线程是CG垃圾回收线程。

猜你喜欢

转载自www.cnblogs.com/skynomonarch/p/8976038.html