线程
来源:互联网 发布:linux更改管理员密码 编辑:程序博客网 时间:2024/06/05 22:25
一、什么是线程?
进程:系统所运行一个程序
线程:进程里面分出的一小段一小段的分段单位
一个进程里面有多个线程
二、怎样创建线程?
1 两种方式创建线程
a 继承Thread类, 覆盖run()方法, 提供并发运程的过程
b 创建这个类的实例
c 使用start() 方法启动线程
/**************调用run()和调用start()有什么区别? **********************/
/**********直接调用run()方法就是直接执行一个普通的方法,并没有启动线程,所以会一直执行这个方法,直到所有语句执行完成‘
调用start()方法是启动一个线程,当有多个线程同时启动时,程序则是先执行会这个线程在执行会那个线程 **********/
2)实现Runnable接口
a 实现Runnable接口, 实现run()方法, 提供并发运程的过程
b 创建这个类的实例, 用这个实例作为Thread构造器参数创建Thread类.
c 使用start() 方法启动线程class Foo implements Runnable{
public void run(){
//....
}
}
Thread t = new Thread(new Foo());
t.start(); //扩展性比较好
thread其实也是实现了runnable接口
/*****************为什么有个thread类还会出现runnable接口呢?*************************************/
由于一个子类继承了thread类以后变不能继承其他类,产生了一定的局限性,为了解决此问题,特出现了接口runnable 这样一个student类要做线程时,并且还拥有了person类的特性,我们便可以选择
class student extends Person implement runnable
{
private void run()
{
}
}
public abstract interface java.lang.Runnable {
// Method descriptor #1 ()V
public abstract void run();
}
2 Sleep 的打断唤醒
1) Thread.sleep(times) 使当前线程从 Running 放弃处理器进入Block状态, 休眠times毫秒, 再返回到Runnable
2)一个线程可以提前唤醒另外一个sleep Block的线程 interrupt() 打断/中断
3 异步, 同步
1) 异步: 并发, 各干自己的: 如: 一群人上卡车
2) 同步: 步调一致的处理, 如: 一群人排队上公交车
多线程的同步问题
/*****************两个或者两个以上的线程启动,我们称之多线程,而为什么在多线程的运行的时候我们有同步的问题?而多线程的同步又有什么好处?******************/
在我们运行多线程的时候可能因为一个线程运行到某一句语句的时候cpu分配到了另一个线程使得第一个线程挂死,而第二个线程执行下面的语句,过了一会cpu从新分配到第一个线程,第一个线程开始执行下面的语句,此时此句语句的数量就有可能发生改变,从而出现漏数,或者超出数量的情况,存在安全隐患。
为了很好的解决此问题,加入了锁的机制synchronized
加入锁,有了同步,,,,比如:排队上厕所
例子:排队买票
class ticket
{
private int ticket=100;
}
4) 案例异步写文件
1) 一个线程负责将控制台信息读取到LinkedList
如果控制台输入quit 将结束输入. 中断写出线程
2) 一个线程负责将LinkedList的信息写到test2.txt
每次检查LinkedList是否有数据, 如果有就写出, 直到空为止
如果没有数据就休眠5秒
写出线程是后台线程, 可以自动结束
import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.PrintWriter;import java.util.Scanner;import java.util.LinkedList;public class Demo6 { public static void main(String[] args) throws IOException {// 1) 一个线程负责将LinkedList的信息写到test2.txt//每次检查LinkedList是否有数据, 如果有就写出, 直到空为止//如果没有数据就休眠5秒//a Scanner b LinkedList c PrintWriter Scanner scanner = new Scanner(System.in); final LinkedList<String> linkedList = new LinkedList<String>(); final PrintWriter out = new PrintWriter(new FileOutputStream("src/test2.txt")); final Thread writer = new Thread(){ public void run(){ while(true){//1 先看linkedList是否有数据,没有休眠5秒,// 把缓冲区的数据冲刷到test2.txt if(linkedList.isEmpty()){ try { System.out.println("linkedList为空"); out.flush(); Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } continue;//如果集合为空,则结束本次循环 }//2 LinkedList有数据写出(把数据从集合中删除,并写到文件当中)//removeFirst():删除该linkedList中的第个元素,并返回删除的元素 String str = linkedList.removeFirst(); System.out.println("写入数据"); out.println(str);//队列: 先进先出去 } } };//当reader结束的时候,后台线程writer也跟着结束 writer.setDaemon(true);// 2) 一个线程负责将控制台信息读取到LinkedList// 如果控制台输入quit 将结束输入. 中断写出线程 Thread reader = new Thread(){ public void run(){ Scanner sc = new Scanner(System.in); while(true){ String str = sc.nextLine(); linkedList.addLast(str); if("quit".equals(str)){ writer.interrupt(); break; } } } }; reader.start(); writer.start(); }}
线性并发安全问题
1) 多个线程并发读写同一个临界资源时候会发生" 线程并发安全问题"
2) 常见的临界资源:
多线程共享实例变量
静态公共变量
3) 使用同步代码块解决线程并发安全问题
synchronized(同步监视器){
}
a 同步监视器 是一个任意对象实例. 是一个多个线程之间的互
斥的锁机制. 多个线程要使用同一个"监视器"对象 实现同步互斥
b 常见写法:
synchronized(this){
// 把当前的资源跟当前访问的线程绑定在一起
}
c 如果方法的全部过程需要同步, 可以简单使用 synchronized
修饰方法. 相当于整个方法的 synchronized(this)
d 尽量减少同步范围, 提高并发效率