码迷,mamicode.com
首页 > 编程语言 > 详细

【学习笔记】java多线程编程

时间:2015-04-17 22:09:15      阅读:133      评论:0      收藏:0      [点我收藏+]

标签:

创建线程

通过以下两种方法创建 Thread 对象:
声明一个 Thread 类的子类,并覆盖 run() 方法。 class mythread extends Thread {
           public void run( ) {/* 覆盖该方法*/ }
      }
声明一个实现 Runnable 接口的类,并实现 run() 方法。 
    class mythread implements Runnable{
           public void run( ) {/* 实现该方法*/ }
     }

 

一. Thread 类

在Java程序启动时,一个线程立刻运行,该线程通常称为程序的主线程。
主线程的重要性体现在两个方面: 
它是产生其他子线程的线程。
通常它必须最后完成执行,因为它执行各种关闭动作。
线程的使用场合
用于处理时间比较久的积序
用于IO的阻塞操作

Thread常用方法

重要方法
start()            启动线程;
setPriority(int p)    设置线程的优先级;
interrupt()        有条件中断线程;
sleep(long s)         (static)使线程睡眠;让出cpu资源; 
currentThread()     (static)获取当前正在执行的线程; 
isAlive()        判断线程是否在活动状态;
yield()            让出cpu资源;
setDaemon(boolean b)    是否是守护线程;
jion()            等待线程消亡;

举例代码:

public class TestExtendThread extends Thread {

    public void run() {
        while(true){
            System.out.println("Run方法 " );
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        // 主线程可以创建其他子线程
        TestExtendThread thread = new TestExtendThread();
        thread.start(); //开启线程
        
        for (int i = 0; i < 100; i++){
            System.out.println("Main主线程" + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

运行结果:

Run方法 
Main主线程0
Run方法 
Main主线程1
Run方法 
Main主线程2
Run方法 
Main主线程3
Run方法 
Main主线程4
Run方法 

 

二. 实现Runnable接口

实现Runnable接口
    public class ImplRunnable implements Runnable{
        public void run(){
            //线程要执行的代码
        } 
    }
创建并启动线程
    ImplRunnable ir = new ImplRunnable();
    Thread thread = new Thread(ir);
    thread.start();

 

举例代码:

public class TestRunable implements Runnable {

    public void run() { //接口Runnable的实现方法重写
        while(true){
            System.out.println("Run方法 " );
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        TestRunable runnable = new TestRunable();
        Thread thread = new Thread(runnable);
        thread.start();
        
        for (int i = 0; i < 100; i++){
            System.out.println("Main主线程" + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

运行结果:

Run方法 
Main主线程0
Main主线程1
Run方法 
Run方法 
Main主线程2
Run方法 
Main主线程3
Main主线程4
Run方法 
Run方法 
Main主线程5
Run方法 
Main主线程6
Run方法 
Main主线程7

 

线程的状态图

 

技术分享

 

join() 方法 :

     join()
          等待该线程终止。

 

未使用join前

public class Testjoin {
    public static void main(String[] args){
        Testone one = new Testone();
        Testtwo two = new Testtwo();
        one.start();
        two.start();
        
        for(int i = 0; i < 100; i++){
            System.out.println("Main主线程" + i);
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Testone extends Thread{
    public void run(){
        while (true) {
            System.out.println("线程1");
            try {
                Thread.sleep(200);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

class Testtwo extends Thread{
    public void run() {
        while (true) {
            System.out.println("线程2");
            try {
                Thread.sleep(200);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

运行结果:

Main主线程0
线程1
线程2
线程1
线程2
Main主线程1
线程2
Main主线程2
线程1
线程2
线程1
Main主线程3
线程1
线程2
Main主线程4
线程2
线程1
Main主线程5
线程2
线程1
........

 

使用join方法:

public class Testjoin {
    public static void main(String[] args){
        Testone one = new Testone();
        Testtwo two = new Testtwo();
        /*
         * 在one.start后面使用one.join方法
         * 将等待该进程完成后再继续其他进程的使用
         */
        one.start();
        try {
            one.join();
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        
        two.start();
        
        for(int i = 0; i < 100; i++){
            System.out.println("Main主线程" + i);
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Testone extends Thread{
    public void run(){
        for (int i = 0; i < 10; i++) {
            System.out.println("线程1");
            try {
                Thread.sleep(200);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

class Testtwo extends Thread{
    public void run() {
        while (true) {
            System.out.println("线程2");
            try {
                Thread.sleep(200);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

运行结果:

线程1
线程1
线程1
线程1
线程1
线程1
线程1
线程1
线程1
线程1
线程2
Main主线程0
线程2
Main主线程1
线程2
Main主线程2
线程2
Main主线程3
线程2

 

同样的,yield() 方法 暂停当前正在执行的线程对象,并执行其他线程。也就是说作用于join相反

线程的优先级

Java 中的线程优先级是在 Thread 类中定义的常量:
NORM_PRIORITY : 值为 5
MAX_PRIORITY : 值为 10
MIN_PRIORITY : 值为 1
缺省优先级为 NORM_PRIORITY
有关优先级的方法有两个:
final void setPriority(int newPriority ) : 修改线程的当前优先级
final int getPriority() : 返回线程的优先级

 

二. 停止线程

可能使线程暂停执行的条件

线程优先级比较低,因此它不能获得 CPU 时间。
使用 sleep( ) 方法使线程睡眠。
通过调用 wait( ) 方法,使线程等待。 
通过调用 yield( ) 方法,线程已显式出让CPU控制权。
线程由于等待一个文件I/O事件被阻塞。
结束线程

尽量不使用stop()或者destroy()方法来结束线程,可能会产生死锁,应尽量让线程中run方法运行正常结束的方法
结束线程可以使用以下三种方法:
修改标志
interrupt()
引发异常

方法一:修改标志

package com.study233;

public class StopThread_flag extends Thread {
    private boolean isStop = false;
    
    public void run(){
        while (this.isStop == false){
            System.out.println("线程运行");
        }
        try {
            Thread.currentThread().sleep(100);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public void shopThread(){
        this.isStop = false;
        try {
            this.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } 
    }
    
    public static void main(String[] args){
        StopThread_flag stf = new StopThread_flag();
        stf.start();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        stf.shopThread();
        
    }
}

运行结果:

线程运行
线程运行
线程运行
线程运行
线程运行
线程运行
线程运行
线程运行
线程运行
线程运行
线程运行
线程停止!

方法二:interrupt()

适用于睡眠或者等待
public void run(){
    while(!this.isInterrupted()){
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                return;
            }
        }        
    }
此类线程只要调用interrupt()方法就可以终止线程。 

方法三:引发异常

适用于阻塞(如监听连接,读网络上发来的数据)
    public void run(){
        byte[] buf = new byte[2048];
        int len;
        while(true){
            try{
               //bi是缓冲输入流
                    len = bi.read(buf);
                    //其他代码
           }catch(IOException e){
               //异常处理
               break;    //跳出循环,线程也就结束。
           }
        }    
    }

 

三. 线程同步问题

并发访问问题

有时两个或多个线程可能会试图同时访问一个资源
 例如,一个线程可能尝试从一个文件中读取数据,而另一个线程则尝试在同一文件中修改数据。
例如,100个线程同时往一个帐户存钱。
在此情况下,数据可能会变得不一致
那如何解决这个问题呢?

如果同步:
同步基于“监视器”这一概念。“监视器”是用作互斥锁的对象;在给定时刻,只有一个线程可以拥有监视器。Java中所有的对象都拥有自己的监视器。
两种方式实现同步:
使用同步方法
    synchronized void methodA() {  }
使用同步块
    synchronized(object) {
        //要同步的语句
    }
锁的概念:
对象锁,锁住该方法或者该变量所在的对象或者类

 

方法同步一:synchronized void methodA() {  }

class Testone extends Thread{
    public synchronized void run(){
        for (int i = 0; i < 10; i++) {
            System.out.println("线程1" + i);
            try {
                Thread.sleep(200);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

方法同步二:使用同步块

技术分享

 

【学习笔记】java多线程编程

标签:

原文地址:http://www.cnblogs.com/hlwyfeng/p/4435708.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!