Java面试题之Java基础部分(6)

51、启动一个线程是用run()还是start()?

启动线程肯定要用start()方法

start()方法:用来启动一个线程,这时此线程处于就绪状态,然后通过调用此线程的run()方法来完成线程的运行操作。(当用start()开始一个线程后,线程就进入就绪状态,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。当cpu分配给它时间时,才开始执行run()方法(如果有的话))。

run()方法:这只是一个方法,直接调用该方法只是把该方法的函数体给执行了一遍,并没真正启动一个线程

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

分几种情况:

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

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

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

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

53、线程的基本概念、线程的基本状态以及状态之间的关系

进程中独立运行的程序片段叫做线程。

Java中的线程有四种状态分别是:运行、就绪、阻塞、死亡。

Java面试题之Java基础部分

【扩展】进程与线程的区别:(面试题)

1.进程有独立的进程空间,进程中的数据存放空间(堆空间和栈空间)是独立的。

2.线程的堆空间是共享的,栈空间是独立的,线程消耗的资源也比进程小,相互之间可以影响的。

54、简述synchronizedjava.util.concurrent.locks.Lock的异同?

主要相同点:Lock能完成synchronized所实现的所有功能

主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放。Lock还有更强大的功能,例如,它的tryLock方法可以非阻塞方式去拿锁。

55、设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少

class ThreadTest {
    private int j;
    public static void main(String args[]) {
        ThreadTest tt = new ThreadTest();
        Inc inc = tt.new Inc();
        Dec dec = tt.new Dec();
        for (int i = 0; i < 2; i++) {
            Thread t = new Thread(inc);
            t.start();
            t = new Thread(dec);
            t.start();
        }
    }
 
    private synchronized void inc() {
        j++;
        System.out.println(Thread.currentThread().getName() + "-inc:" + j);
    }
 
    private synchronized void dec() {
        j--;
        System.out.println(Thread.currentThread().getName() + "-dec:" + j);
    }
 
    class Inc implements Runnable {
        public void run() {
            for (int i = 0; i < 100; i++) {
                inc();
            }
        }
    }
 
    class Dec implements Runnable {
        public void run() {
            for (int i = 0; i < 100; i++) {
                dec();
            }
        }
    }
}

56、子线程循环10次,接着主线程循环100,接着又回到子线程循环10次,接着再回到主线程又循环100,如此循环50次,请写出程序。

public class TraditionalThreadCommunication {
 public static void main(String[] args) {
  final Business bussiness = new Business();
  new Thread(
    new Runnable(){
   public void run() {
    for(int j=1; j<=50;j++){
     bussiness.sub(j);
    }
   } 
    } 
  ).start();
 
  new Thread(
   new Runnable(){
    public void run() {
     for(int j=1; j<=50;j++){
      bussiness.main(j);
     } 
    } 
    } 
  ).start();
 }
}

class Business{
 boolean bShouldSub = true;
 public synchronized void sub(int j){
  if(!bShouldSub){
   try {
    this.wait();
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
  for(int i=1;i<=10;i++){
   System.out.println("子线程循环。。。" + i);
  }
  bShouldSub = false;
  this.notify();
 }
 
 public synchronized void main(int j){
  if(bShouldSub){
   try {
    this.wait();
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
  for(int i=1;i<=30;i++){
   System.out.println("主线程循环。。。" + i);
  }
  bShouldSub = true;
  this.notify(); // 喚醒。
 }
}

下面使用jdk5中的并发库来实现的:

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ConditionThreadCommunication {
 public static void main(String[] args) {
  final Business business = new Business();
  /*子线程*/
  new Thread(new Runnable(){
   public void run() {
    for(int i = 1; i <= 50; i++){
     business.sub(i);
    }
   }
  }).start();
 
  /*主线程*/
  for(int i = 1; i <= 50; i++){
   business.main(i);
  }
 }
 
 static class Business {//处理线程安全归为一类,这样用的就是同一把同步锁
 private boolean subShouldRun = true; //当为true时子线程执行,当为false时主线程执行
 private Lock lock = new ReentrantLock();//创建一把锁
 private Condition condition = lock.newCondition();//创建condition操作等待与唤醒操作
 
  public void sub(int i)
  {
   lock.lock();//打开锁
   try
   {
    while(!subShouldRun)
    {
     try {
      //this.wait();//等待线程
      condition.await();//condition等待
     } catch (Exception e) {
      e.printStackTrace();
     }
    }
    for(int j = 1; j <= 10; j++)
    {
     System.out.println("sub Thread sequence of " + j + ", loop of " + i);
    }
    subShouldRun = false;
    //this.notify();//唤醒线程
    condition.signal();//condition唤醒线程
   }finally
   {
    lock.unlock();//关闭锁
   }
  }
 
  public void main(int i)
  {
   lock.lock();//打开锁
   try
   {
    while(subShouldRun)
    {
     try {
      //this.wait();
      condition.await();
     } catch (Exception e) {
      e.printStackTrace();
     }
    }
    for(int j = 1; j <= 100; j++)
    {
     System.out.println("main Thread sequence of " + j + ", loop of " + i);
    }
    subShouldRun = true;
    //this.notify();
    condition.signal();
   }finally
   {
    lock.unlock();//关闭锁
   }
  }
 }
}

57、介绍Collection框架的结构

Collection

|-----List 有顺序可重复

|-----ArrayList

是数组实现 它是线程不安全的。它每一次添加后都会增长50%长度它在执行查找操作时效率比较高

|-----LinkedList 是链表实现,它在执行修改或插入时效率比较高。 它是线程不安全的。

|-----Vector 它也是数组实现,它是线程安全的 它每一次添加后都会增长100%长度无论是查找还是修改删除操作效率都比较低。

|-----Set 无顺序不重复

|----HashSet 底层实现是使用hash表,特点是无顺序不可重复;HashSet维护元素的唯一性是使用元素的hashCodeequals实现的。

|------LinkedHashSet 它的特点保证添加时的顺序与取出时的顺序一样。

|-----TreeSet 特点:有顺序的不重复,底层实现是使用二叉树

【扩展】类集框架的完整结构(Collection)

框架的完整结构(Collection)

1.类集框架最大的接口:CollectionMapIteratorEnumeration

2.Collection:存放单值

|- List:允许有重复内容,有序

|- ArrayList:异步处理,新的操作类,非线程安全。

|- Vector:同步处理,旧的操作类,线程安全。支持Enumeration输出

|- Set:不允许有重复内容,无序,靠hashCoke()equals()进行重复的严重

|- HashSet:无序存放

|- TreeSet:有序存放,安Comparable排序

3.Map:存放一对值

|- HashMap:新的类,异步处理,非线程安全,允许有null

|- Hashtable:旧的类,同步处理,线程安全,不允许有null

|- Properties:属性操作类

|- TreeMap:有序排列,按key排序,根据Comparable指定排序规则

4.Iterator:

|- 迭代输出,依靠Collection接口中的iterator方法输出,是新的输出标准

5.Enumeration:旧的输出标准

58Collection框架中实现比较要实现什么接口

comparable/comparator

【扩展】comparablecomparator的区别

1Comparable 用作默认的比较方式 ,需要覆盖compareTo方法。

Comparator 用作自定义的比较方式,当默认的比较方式不适用时或者没有提供默认的比较方式,使用Comparator, 需要覆盖compare方法

2comparable属于java.lang包,comparator属于java.util

3)像ArraysCollections中的排序方法,当不指定Comparator时使用的就是默认排序方式,也就是使用Comparable。指定Comparator时就是使用提供的比较器。

sort(Object[]) 所有的对象都必须实现Comparable接口,它用来确定对象之间的大小关系

sort(Object[], Comparator) 对象不必实现Comparable接口,由Comparator来确定对象之间的大小关系。

59、ArrayListVector的区别

(1)ArrayList :是数组实现 它是线程不安全的。它每一次添加后都会增长50%长度.它在执行查找操作时效率比较高;

2Vector 它也是数组实现,它是线程安全的 它每一次添加后都会增长100%长度,无论是查找还是修改删除操作效率都比较低。(同步性和数据增长)

 

60、HashMapHashtable的区别

HashMap:新的类,异步处理,非线程安全,允许有null

Hashtable:旧的类,同步处理,线程安全,不允许有null

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/417b4bdbdf5aba80bc7782bea7f3f981.html