首页 > 代码库 > javaSE复习总结3

javaSE复习总结3

1、线程

Thread类:

  public final String getName():返回该线程的名称

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

  getThreadGroup():返回该线程所属的线程组。

 

线程控制:

  public static void sleep(long millis):线程休眠

  public final void join():线程加入( 等待该线程终止)

  public static void yeild():线程礼让(暂停当前正在执行的线程对象,并执行其他线程。)

  public final void setDaemon(boolean on):后台线程

  public final void stop():  已过时。 该方法具有固有的不安全性。用 Thread.stop 来终止线程将释放它已经锁定的所有监视器

  public void interrupt():   中断线程。

 

多线程的实现方案:

1)继承Thread类

步骤
 A:自定义类MyThread继承Thread类。
 B:MyThread类里面重写run()
 C:创建对象
 D:启动线程

public class MyThread extends Thread {

public void run() {
for (int x = 0; x < 200; x++) {
System.out.println(x);
}
}

}

 

public class MyThreadDemo {
public static void main(String[] args) {

  // run():仅仅是封装被线程执行的代码,直接调用是普通方法
  // start():首先启动了线程,然后再由jvm去调用该线程的run()方法。

  // IllegalThreadStateException:非法的线程状态异常

// 创建两个线程对象
  MyThread my1 = new MyThread();
  MyThread my2 = new MyThread();

// 启动线程

  my1.start();
  my2.start();
}
}

 

2)实现Runnable接口(实现接口可以避免java单继承带来的局限性)

步骤:
 A:自定义类MyRunnable实现Runnable接口
 B:重写run()方法
 C:创建MyRunnable类的对象
 D:创建Thread类的对象,并把C步骤的对象作为构造参数传递

 

public class MyRunnable implements Runnable {

public void run() {
for (int x = 0; x < 100; x++) {
// 由于实现接口的方式就不能直接使用Thread类的方法了,但是可以间接的使用
System.out.println(Thread.currentThread().getName() + ":" + x);
}
}

}

 

public class MyRunnableDemo {
public static void main(String[] args) {
// 创建MyRunnable类的对象
  MyRunnable my = new MyRunnable();

// 创建Thread类的对象,并把C步骤的对象作为构造参数传递

// Thread(Runnable target, String name)
  Thread t1 = new Thread(my, "aa");
  Thread t2 = new Thread(my, "bb");

  t1.start();
  t2.start();
}
}

 

解决线程安全问题:

1)同步代码块:

  synchronized(对象){
  需要同步的代码;
  }


同步可以解决安全问题的根本原因就在那个对象上。该对象如同锁的功能。多个线程必须是同一把锁。

public class SellTicket implements Runnable {
// 定义100张票
  private int tickets = 100;
//创建锁对象
  private Object obj = new Object();


@Override
public void run() {
  while (true) {
  synchronized (obj) {
    if (tickets > 0) {
      try {
        Thread.sleep(100);
      } catch (InterruptedException e) {
        e.printStackTrace();
  }
    System.out.println(Thread.currentThread().getName()+ "正在出售第" + (tickets--) + "张票");
}
}
}
}
}

 

 

2)同步方法:把同步加在方法上

  普通方法(同步对象是this)

private synchronized void sellTicket() {

if (tickets > 0) {
   try {
  Thread.sleep(100);
} catch (InterruptedException e) {
     e.printStackTrace();
   }
  System.out.println(Thread.currentThread().getName()+ "正在出售第" + (tickets--) + "张票 ");
   }
}

 

public void run() {
while (true) {
if(x%2==0){
synchronized (this) {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ "正在出售第" + (tickets--) + "张票 ");
}
}
}else {}

 

静态方法的锁对象是:类的字节码文件对象

private static synchronized void sellTicket() {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ "正在出售第" + (tickets--) + "张票 ");
}
}
}

 

public void run() {
while (true) {
if(x%2==0){
synchronized (SellTicket.class) {//这里不可能是this,因为静态中没有this 静态是随着类的加载而加载,首先进内存的是类的字节码文件
if (tickets > 0) {
try {
Thread.sleep(100);

 

Lock锁

  void lock():获取锁。(如果锁不可用,出于线程调度目的,将禁用当前线程,并且在获得锁之前,该线程将一直处于休眠状态。)

  void unlock():释放锁

 

public class SellTicket implements Runnable {

// 定义票
  private int tickets = 100;

// 定义锁对象
  private Lock lock = new ReentrantLock();

@Override
  public void run() {
  while (true) {
    try {
// 加锁
      lock.lock();
      if (tickets > 0) {
      try {
        Thread.sleep(100);
      } catch (InterruptedException e) {
         e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName()+ "正在出售第" + (tickets--) + "张票");
  }
} finally {
// 释放锁
  lock.unlock();
}
}
}

}

 

 

线程池:(线程池里的每一个线程代码结束后并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用)

  程序启动一个新线程的成本很高,因为涉及到与操作系统的交互,而使用线程池可以很好的提高性能

 

JDK5新增了Executors工厂类来产生线程池

方法:

  public static ExectorService newCachedThreadPool():开启具有缓存功能的线程池

  public static ExectorService newFixedThreadPool(int nThreads):创建指定数量的线程池

  public static ExectorService  newSingleThreadExector():创建一个

这些方法的返回值是ExectorsService对象,该对象表示一个线程池,可以执行Runnable对象和Callable对象代表的线程

 

public static void main(String[] args) {
// 创建一个线程池对象,控制要创建几个线程对象。
// public static ExecutorService newFixedThreadPool(int nThreads)
  ExecutorService pool = Executors.newFixedThreadPool(2);

// 可以执行Runnable对象或者Callable对象代表的线程

//Future<?> submit(Runnable task):     提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。
// <T> Future<T> submit(Callable<T> task): 提交一个返回值的任务用于执行,返回一个表示任务的未决结果Future。


  pool.submit(new MyRunnable());
  pool.submit(new MyRunnable());

//结束线程池
  pool.shutdown();//如果不加结束语句,那么线程执行完毕后重新返回池中,以供其他人使用
}

 

public class MyRunnable implements Runnable {

@Override
public void run() {
for (int x = 0; x < 100; x++) {
System.out.println(Thread.currentThread().getName() + ":" + x);
}
}

}

 

 

定时器:

Timer:(extends Object)一种工具,线程用其安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行。

  Timer()
          创建一个新计时器。

  schedule(TimerTask task, long delay)
          安排在指定延迟后执行指定的任务。

  schedule(TimerTask task, long delay, long period)
          安排指定的任务从指定的延迟后开始进行重复的固定延迟执行

  cancel()
          终止此计时器,丢弃所有当前已安排的任务。

 

TimerTask(extends Object  implements Runnable

  TimerTask()
          创建一个新的计时器任务

  run()
          此计时器任务要执行的操作。

  cancel()
          取消此计时器任务。

jvm虚拟机的启动是单线程的还是多线程的?
  多线程的。
   原因是垃圾回收线程也要先启动,否则很容易会出现内存溢出。
     现在的垃圾回收线程加上前面的主线程,最低启动了两个线程,所以,jvm的启动其实是多线程的。

 

 

2、设计模式

1)单例设计模式

  饿汉式:

  懒汉式:(延迟加载)

 

javaSE复习总结3