java多线程
创建线程的两种传统方式
1).在Thread子类覆盖的run方法中编写运行代码
- Thread thread1=new Thread(){
- @Override
- publicvoid run() {
- while(true){
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("0 : "+Thread.currentThread ().getName());
- }
- }
- };
- thread1.start();
Thread thread1=new Thread(){ @Override public void run() { while(true){ try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("0 : "+Thread.currentThread ().getName()); } } }; thread1.start();
2).在传递给Thread对象的Runnable对象的run方法中编写代码
- Thread thread2=new Thread(new Runnable() {
- @Override
- publicvoid run() {
- while(true){
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("1 : "+Thread.currentThread().getName());
- }
- }
- });
- thread2.start();
Thread thread2=new Thread(new Runnable() { @Override public void run() { while(true){ try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("1 : "+Thread.currentThread().getName()); } } }); thread2.start();
总结:查看Thread类的run()方法的源代码,可以看到其实这两行方式都是在调用Thread对象的run方 法,如果Thread类的run方法没有被覆盖,并且为该Thread对象设置了一个Runnable对象,该run 方法会调用Runnable对象的run方法。
如果在Thread子类覆盖的run方法中编写了运行代码,也为Thread子类对象传递了一个Runnable对象 ,那么,线程运行时的执行代码是子类的Run方法的代码。
- new Thread(new Runnable() {
- @Override
- publicvoid run() {
- while(true){
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("runnable : "+Thread.currentThread().getName());
- }
- }
- }){
- publicvoid run() {
- while(true){
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("thread : "+Thread.currentThread().getName());
- }
- };
- }.start();
new Thread(new Runnable() { @Override public void run() { while(true){ try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("runnable : "+Thread.currentThread().getName()); } } }){ public void run() { while(true){ try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("thread : "+Thread.currentThread().getName()); } }; }.start();
输出结果为thread : Thread-2
2.定时器的应用 1)Timer类 2)TimerTask类
- new Timer().schedule(new TimerTask() {
- @Override
- publicvoid run() {
- System.out.println("bombing");
- }
- }, 10000,3000);
new Timer().schedule(new TimerTask() { @Override public void run() { System.out.println("bombing"); } }, 10000,3000);
3.线程的同步互斥与通信
1)使用synchronized代码块及其原理 public void output(String name){ synchronized (this) { for (int i = 0; i < name.length(); i++) { System.out.print(name.charAt(i)+" "); } System.out.println(); } } 2)使用synchronized方法 class OutPuter{ public synchronizedvoid output(String name){ for (int i = 0; i < name.length(); i++) { System.out.print(name.charAt(i)+" "); } System.out.println(); } }
面试题:子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着再回到主线程又 循环100次,如此循环50次,请写出程序。
- publicclass TraditionalThreadCommunication {
- /**
- * @param args
- */
- publicstaticvoid main(String[] args) {
- final Business business=new Business();
- //子线程
- new Thread(new Runnable() {
- @Override
- publicvoid run() {
- for (int i = 1; i <=50; i++) {
- business.sub(i);
- }
- }
- }).start();
- //主线程
- for (int i = 1; i <=50; i++) {
- business.main(i);
- }
- }
- }
- class Business{
- privateboolean bShouldSub=true;
- publicsynchronizedvoid sub(int i){
- while(!bShouldSub){
- try {
- this.wait();//等待
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- for (int j = 1; j <= 10; j++) {
- System.out.println("sub thread sequence of " + j
- + " , loop of " + i);
- }
- bShouldSub=false;
- this.notify();//唤醒(防止死锁)
- }
- publicsynchronizedvoid main(int i){
- while(bShouldSub){
- try {
- this.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- for (int j = 1; j <= 20; j++) {
- System.out.println("main thread sequence of " + j
- + " , loop of " + i);
- }
- bShouldSub=true;
- this.notify();
- }
- }
public class TraditionalThreadCommunication { /** * @param args */ public static void main(String[] args) { final Business business=new Business(); //子线程 new Thread(new Runnable() { @Override public void run() { for (int i = 1; i <=50; i++) { business.sub(i); } } }).start(); //主线程 for (int i = 1; i <=50; i++) { business.main(i); } } } class Business{ private boolean bShouldSub=true; public synchronized void sub(int i){ while(!bShouldSub){ try { this.wait();//等待 } catch (InterruptedException e) { e.printStackTrace(); } } for (int j = 1; j <= 10; j++) { System.out.println("sub thread sequence of " + j + " , loop of " + i); } bShouldSub=false; this.notify();//唤醒(防止死锁) } public synchronized void main(int i){ while(bShouldSub){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } for (int j = 1; j <= 20; j++) { System.out.println("main thread sequence of " + j + " , loop of " + i); } bShouldSub=true; this.notify(); } }
(总结:要用到共同数据(包括同步锁)的若干个方法,应该归在同一个类身上,这种设计正好体现了高类聚和程序的健壮性。)