多线程总结

什么是线程 他和进程的区别

线程就是系统进行运算调度的最小单位 他包含在进程中 是进程的实际运行单位
线程是进程的子集 一个进程中有很多线程 线程则是共享进程的内存空间
1.进程是程序的一次执行
2.进程是一个程序及其数据在处理机上顺序执行时所发生的活动
3.进程是程序在一个数据集合上运行的过程,他是系统进行资源分配和调度的一个独立单位


线程的生命周期 创建 运行阻塞就绪 销毁

线程创建的三种方式

第一种 继承Thread类

public class MyThread extends Thread{//继承Thread类

  public void run(){

  //重写run方法

  }

}

第二种 实现runnable接口 重写run方法

public class MyThread2 implements Runnable {//实现Runnable接口

  public void run(){

  //重写run方法

  }

}

public class Main {

  public static void main(String[] args){

    //创建并启动线程

    MyThread2 myThread=new MyThread2();

    Thread thread=new Thread(myThread);

    thread().start();

    //或者    new Thread(new MyThread2()).start();

  }

}

第三种 实现callable接口 实现call方法

public class CallableThreadTest implements Callable<Integer>  {  

public static void main(String[] args)  
{  
    CallableThreadTest ctt = new CallableThreadTest();  
    FutureTask<Integer> ft = new FutureTask<>(ctt);  
    for(int i = 0;i < 100;i++)  
    {  
        System.out.println(Thread.currentThread().getName()+" 的循环变量i的值"+i);  
        if(i==20)  
        {  
            new Thread(ft,"有返回值的线程").start();  
        }  
    }  
    try  
    {  
        System.out.println("子线程的返回值:"+ft.get());  
    } catch (InterruptedException e)  
    {  
        e.printStackTrace();  
    } catch (ExecutionException e)  
    {  
        e.printStackTrace();  
    }  

}  

@Override  
public Integer call() throws Exception  
{  
    int i = 0;  
    for(;i<100;i++)  
    {  
        System.out.println(Thread.currentThread().getName()+" "+i);  
    }  
    return i;  
}  

}


volatile变量指的是什么?
他是一个成员变量的修饰符 保证下一个读操作是在写操作之后发生
并发编程的三个概念
原子性 一些操作 要么全部执行 要么都不执行
可见性 指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值
有序性 :即程序执行的顺序按照代码的先后顺序执行。

一些规则

锁定规则:一个unLock操作先行发生于后面对同一个锁额lock操作
volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作
传递规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C
线程启动规则:Thread对象的start()方法先行发生于此线程的每个一个动作
线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生
线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行
什么是线程安全
你代码所在的类有多个线程同时运行如果每次运行结果和单线程 运行结果一样 而且其他变量的值和预期的一样 那么说他就是线程安全的

如何去停止线程

正常情况下为run方法或call方法执行完之后线程就会终止
使用共享变量的方式

public class ThreadFlag extends Thread 
{ 
public volatile boolean exit = false; 
public void run() { while (!exit); } 
public static void main(String[] args) throws Exception { 
   ThreadFlag thread = new ThreadFlag();
    thread.start(); 
    sleep(3000); // 主线程延迟3秒 
    thread.exit = true; // 终止线程thread
    thread.join();
   System.out.println("线程退出!");
    } 
} 

使用interrupt
而是使用Thread提供的interrupt()方法,因为该方法虽然不会中断一个正在运行的线程,但是它可以使一个被阻塞的线程抛出一个中断异常,从而使线程提前结束阻塞状态,退出堵塞代码。


class MyThread extends Thread { 
   volatile boolean stop = false;
   public void run() { 
    while (!stop) {
     System.out.println(getName() + " is running");
     try { sleep(1000); } 
     catch (InterruptedException e) { 
     System.out.println("week up from blcok...");
     stop = true; // 在异常处理代码中修改共享变量的状态
      } 
      } 
      System.out.println(getName() + " is exiting..."); } }

class InterruptThreadDemo3 {
 public static void main(String[] args) throws InterruptedException {
  MyThread m1 = new MyThread(); 
  System.out.println("Starting thread..."); 
  m1.start(); 
  Thread.sleep(3000);
   System.out.println("Interrupt thread...: " + m1.getName()); m1.stop = true; // 设置共享变量为true m1.interrupt(); // 阻塞时退出阻塞状态 Thread.sleep(3000); // 主线程休眠3秒以便观察线程m1的中断情况 System.out.println("Stopping application..."); 
   } 
   }

**如何在两个线程间共享数据
1可以使用同一个对象
public class Ticket implements Runnable{

private int ticket = 10;
public void run() {
    while(ticket>0){
        ticket--;
        System.out.println("当前票数为:"+ticket);
    }

}


}

public class SellTicket {


/**
 * @param args
 */
public static void main(String[] args) {
    Ticket t = new Ticket();
    new Thread(t).start();
    new Thread(t).start();
}

}
2如果两个线程执行的代码不同 可以实现两个个对象 可以将共享数据分别传递给连个不同线程

3可以把这两个线程作为内部类 共享成员变量**
即把要共享的数据变得全局变量,这样就保证了操作的是同一份数据。同时内部类的方式使代码更加简洁。但是不如第一种解法条理那么清楚。

public class MyData {
     private int j=0;
     public  synchronized void add(){
         j++;
         System.out.println("线程"+Thread.currentThread().getName()+"j为:"+j);
     }
     public  synchronized void dec(){
         j--;
         System.out.println("线程"+Thread.currentThread().getName()+"j为:"+j);
     }
     public int getData(){
         return j;
     }
}


public class TestThread {


/**
 * @param args
 */
public static void main(String[] args) {
    final MyData data = new MyData();
    for(int i=0;i<2;i++){
        new Thread(new Runnable(){

            public void run() {
                data.add();

            }

        }).start();
        new Thread(new Runnable(){

            public void run() {
                data.dec();

            }

        }).start();
    }
}


}

wait和sleep的区别
sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。
wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。

notify,notifyall,yield
notifyAll使所有原来在该对象上等待被notify的线程统统退出wait的状态,变成等待该对象上的锁,一旦该对象被解锁,他们就会去竞争。
notify他只是选择一个wait状态线程进行通知,并使它获得该对象上的锁,但不惊动其他同样在等待被该对象notify的线程们,当第一个线程运行完毕以后释放对象上的锁,此时如果该对象没有再次使用notify语句,即便该对象已经空闲,其他wait状态等待的线程由于没有得到该对象的通知,继续处在wait状态,直到这个对象发出一个notify或notifyAll,它们等待的是被notify或notifyAll,而不是锁。
yield 线程让步 意思就是让自己或者其他线程运行
interrupt 设置中断标识为true 查询线程中断状态 并清零 中断状态 isinterpupt 是查询其他中断状态并不会改变中断标识

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值