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中的線程有四種狀態分別是:運行、就緒、阻塞、死亡。
【擴展】進程與線程的區別:(面試題)
1.進程有獨立的進程空間,進程中的數據存放空間(堆空間和棧空間)是獨立的。
2.線程的堆空間是共享的,棧空間是獨立的,線程消耗的資源也比進程小,相互之間可以影響的。
54、簡述synchronized和java.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維護元素的唯一性是使用元素的hashCode與equals實現的。
|------LinkedHashSet 它的特點保證添加時的順序與取出時的順序一樣。
|-----TreeSet 特點:有順序的不重複,底層實現是使用二叉樹
【擴展】類集框架的完整結構(Collection)
框架的完整結構(Collection)
1.類集框架最大的接口:Collection、Map、Iterator、Enumeration
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:舊的輸出標準
58、Collection框架中實現比較要實現什麼接口
comparable/comparator
【擴展】comparable與comparator的區別
(1)Comparable 用作默認的比較方式 ,需要覆蓋compareTo方法。
Comparator 用作自定義的比較方式,當默認的比較方式不適用時或者沒有提供默認的比較方式,使用Comparator, 需要覆蓋compare方法
(2)comparable屬於java.lang包,comparator屬於java.util包
(3)像Arrays和Collections中的排序方法,當不指定Comparator時使用的就是默認排序方式,也就是使用Comparable。指定Comparator時就是使用提供的比較器。
sort(Object[]) 所有的對象都必須實現Comparable接口,它用來確定對象之間的大小關係
sort(Object[], Comparator) 對象不必實現Comparable接口,由Comparator來確定對象之間的大小關係。
59、ArrayList和Vector的區別
(1)ArrayList :是數組實現 它是線程不安全的。它每一次添加後都會增長50%長度.它在執行查找操作時效率比較高;
(2)Vector 它也是數組實現,它是線程安全的 它每一次添加後都會增長100%長度,無論是查找還是修改刪除操作效率都比較低。(同步性和數據增長)
60、HashMap和Hashtable的區別
HashMap:新的類,異步處理,非線程安全,允許有null
Hashtable:舊的類,同步處理,線程安全,不允許有null