進程:
線程:
進程與線程區別:
線程使用場合:
實現多線程有幾種方法?
三種,
1.繼承Thread類,重寫run函數
2.實現Runnable接口,重寫run函數
3.實現Callable接口,重寫call函數
thread:
public class testThread {
/**
* 測試多線程併發
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread t1 = new myThread();
Thread t2 = new myThread();
t1.start();
t2.start();
}
}
/*
* 線程
*/
class myThread extends Thread{
public void run(){
for(int i = 1; i <= 100; i++){
System.out.println(i);
}
}
}
runnable:
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class testRunnable extends JFrame implements Runnable{
/**
* 測試runnable
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
testRunnable r = new testRunnable();
r.setSize(300,300);
r.setVisible(true);
r.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Thread t = new Thread(r);
t.start();
}
public void run(){
int i = 0;
JPanel panel = new JPanel();
panel.setSize(300,300);
this.setContentPane(panel);
while(true){
i = i == 0? 1:0;
if(i == 0){
panel.setBackground(Color.BLACK);
}else{
panel.setBackground(Color.YELLOW);
}
}
}
}
使用匿名內部類創建線程:
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class testInnerThread {
/**
* 使用匿名內部類方式創建線程
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
JFrame frame = new JFrame();
frame.setSize(300,300);
final JPanel panel = new JPanel() ;
panel.setSize(300,300);
frame.setContentPane(panel);
frame.setVisible(true);
Thread t = new Thread(){
public void run(){
int i = 0;
while(true){
i = i == 0?1:0;
if(i == 0){
panel.setBackground(Color.BLACK);
}else{
panel.setBackground(Color.WHITE);
}
}
}
};
t.start();
}
}
一道面試題:
Sleep()和wait()有什麼區別?
sleep是線程類(Thread)的方法,導致此線程暫停執行指定時間,把執行機會給其他線程,但是監控狀態依然保持,到時後會自動恢復。調用sleep不會釋放對象鎖。
wait().會釋放鎖
currentThread:
public class testCurrentThread {
/**
* 測試currentThread方法
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("運行main方法的線程是" + Thread.currentThread());
testCurrent();
Thread t = new Thread(){
public void run(){
System.out.println("線程t" + Thread.currentThread());
testCurrent();
}
};
t.start();
}
/**
* 測試不同線程調用該方法時,獲取這個線程
*/
public static void testCurrent(){
System.out.println("運行testcurrent方法的線程是" + Thread.currentThread());
}
}
獲取線程名字及id:
/**
* 獲取線程名字及id
*/
public class testThreadNameAndId {
/**
* 測試getName及getId
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread t = new Thread();
System.out.println(t.getName());
System.out.println(t.getId());
Thread t1 = new Thread();
System.out.println(t1.getName());
System.out.println(t1.getId());
//爲線程自定義名字
Thread t2 = new Thread("黃色潛水艇");
System.out.println(t2.getName());
System.out.println(t2.getId());
}
}
守護線程:
public class testDaemonThread {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread d = new Thread(){
public void run(){
while(true){
System.out.println("後臺線程");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
d.setDaemon(true);
d.start();
try {
//使main線程阻塞五秒
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//進程中所有前臺線程結束後,後臺線程制結束
System.out.println("main線程結束了");
}
}
線程等待join():
public class testJoin {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
final Thread t1 = new Thread(){
public void run(){
for(int i = 0; i <= 10; i++){
System.out.println("t1:正在下載圖片:" + i*10 + "%");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("t1:圖片下載完畢");
}
};
Thread t2 = new Thread(){
public void run(){
System.out.println("等待t1");
try {
t1.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("t2顯示圖片");
}
};
t1.start();
t2.start();
}
}
synchronized: 鎖機制:
兩個線程互斥,synchronized(String string),則string相同。
線程安全與非線程安全:
線程池:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 測試線程池
* @author wangyu
*
*/
public class testExecutorService {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//線程池每次啓動兩個線程來執行任務,由於要求執行五次任務,所以
//線程池要求分三次執行。
ExecutorService threadPool = Executors.newFixedThreadPool(2);
for(int i = 0; i < 5; i++){
Handler handler = new Handler();
threadPool.execute(handler);
}
}
}
class Handler implements Runnable{
public void run(){
String name = Thread.currentThread().getName();
System.out.println("正在執行的線程" + name);
for(int i = 0; i < 10; i++){
System.out.println(name + ":" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(name + "任務完成");
}
}
雙緩衝隊列:
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
/**
* 測試雙緩衝隊列
* (1)首先,使用ArrayBlockingQueue類創建一個大小爲10的雙緩衝隊列
* queue;然後,循環20次向隊列queue中添加元素,如果5秒內元素仍沒有入隊
* 到隊列中,則返回false。
* (2)首先,使用ArrayBlockingQueue類創建一個大小爲10的雙緩衝隊列
* queue;然後,將0到9,10個數字加入到隊列queue中;最後,循環20次從
* 隊列queue中取元素,如果5秒內元素仍沒有入隊,則返回null。
* @author wangyu
*/
public class testBlockingQueue {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
testBlockingQueue tbq = new testBlockingQueue();
// tbq.testOffer();
tbq.testPull();
}
/**
* 測試入隊方法
*/
public void testOffer(){
BlockingQueue <Integer> queue = new ArrayBlockingQueue<Integer>(10);
for(int i = 0; i < 20; i++){
try {
boolean b = queue.offer(i,5,TimeUnit.SECONDS);
System.out.println("存入是否成功" + b);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 測試出隊方法
*/
public void testPull(){
BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10);
for(int i = 0; i < 20; i++){
queue.offer(i);
}
for(int i = 0;i < 20; i++){
//獲取元素,設置5秒超時,5秒內還沒有元素可取回則返回null
try {
Integer num= queue.poll(5, TimeUnit.SECONDS);
System.out.println("元素" + num);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
面試題:
子線程循環10次,接着主線程循環100,接着又子線程循環10次,接着又主線程循環100,如此50次。寫出代碼:
/**
* 子線程循環10次,接着主線程循環100,接着又回到子線程循環10次,接着再回到主線程又循環100,如此循環50次,請寫出程序。
* @author lijinnan
* @date:2013-11-5 下午3:07:10
*/
public class ThreadComunication {
private static final int ROUND_COUNT = 50;
public static void main(String[] args) {
//主線程和子線程“共享”一個Busines實例
final Business business = new Business();
/*
//主線程
for (int i = 0; i < ROUND_COUNT; i++) {
business.main(i);
}
*/
//子線程-注意要先啓動子線程,否則子線程不會啓動,主線程在roundIndex=0執行完畢後就陷入無限等待
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < ROUND_COUNT; i++) {
business.sub(i);
}
}
}).start();
//主線程
for (int i = 0; i < ROUND_COUNT; i++) {
business.main(i);
}
}
}
class Business {
private static final int SUB_COUNT = 10;
private static final int MAIN_COUNT = 100;
private boolean doSub;
public synchronized void sub(int roundIndex) {
while (!doSub) {
try {
wait();
} catch (InterruptedException e) {
//ignore
}
}
for (int i = 0; i < SUB_COUNT; i++) {
System.out.println("sub " + i + " of " + roundIndex);
}
doSub = false;
notifyAll();
}
public synchronized void main(int roundIndex) {
while (doSub) {
try {
wait();
} catch (InterruptedException e) {
//ignore
}
}
for (int i = 0; i < MAIN_COUNT; i++) {
System.out.println("main " + i + " of " + roundIndex);
}
doSub = true;
notifyAll();
}
}