---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Unity开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------
黑马程序员 多线程一、概念
进程:正在进行的程序
线程:就是进程中一个负责程序执行的控制单元(执行路径),一 个进程中可以多执行路径,称为多线程。
二、利和弊
利:多个程序同时执行
弊:效率低
三、创建线程
1、用Thread类创建线程,步骤:
a、继承Thread类
b、覆写Thread类的run()
c、创建Thread类的子类对象创建线程
d、调用start()开启线程并调用线程的任务run方法执行
实例:
//继承Thread类
public class TestThread extends Thread{
//覆盖Thread类的run()
public void run() {
while(true){
System.out.println(Thread.currentThread().getName()+"is running");
}
}
}
public class TestThread2 {
public static void main(String[] args) {
//调用TestThread类的start()开启线程
new TestThread().start();
while (true) {
System.out.println("main Thread is running");
}
}
}
2、使用Runnable接口创建多线程,步骤:
a、实现Runnable接口,覆写run()
b、创建Runnable类的子类实例
c、创建一个Thread类实例,并将Runnable类的子类实例作为构造参数
d、调用start()开启线程
实例:
//实现Runnable接口
public class TestThread implements Runnable{
//覆写run()
public void run() {
while(true){
System.out.println(Thread.currentThread().getName());
}
}
}
public class TestThread2 {
public static void main(String[] args) {
//创建TestThread类的实例
TestThread tt=new TestThread();
//创建一个Thread类的实例,并将子类实例对象做为构造参数
Thread t=new Thread(tt);
//调用start()开启线程
t.start();
while (true) {
System.out.println("main thread is running");
}
}
}
3、两种实现线程方法的比较(常用实现Runnable接口这种方法)
实现Runnable接口比继承Thread类的优点:
a、将线程的任务从线程的子类中分离出来,进行了单独的封装
b、避免了单继承的局限性
实例:4个窗口同时卖100张票
public class TestThread implements Runnable{
private int tickets=100;
public void run() {
while(true){
if(tickets>0)
System.out.println(Thread.currentThread().getName()+"is saling ticket"+tickets--);
}
}
}
public class WindowThread {
public static void main(String[] args) {
TestThread tt=new TestThread();
new Thread(tt).start();
new Thread(tt).start();
new Thread(tt).start();
new Thread(tt).start();
}
}
四、线程安全
1、线程安全问题原因:多个线程操作同一共享数据,一个线程操 作共享数据中,其它线程参与进来,导致读写错误,线程安全问 产生。
2、解决:同步代码块。(一个线程操作同一共享数据时,其它线 程不能参与进来)
格式:synchronized (对象) {需要被同步的代码;}
3、同步的利和弊:利,解决了线程安全问题;弊,效率降低,都 要判断同步锁。
4、同步的前提:同步中必须有多个线程并使用同一个锁。
5、同步函数:只需在需要同步的函数定义前加上synchronized关键字
6、代码块与函数间的同步:代码块和函数使用同一个监视器对象,函数使用的监视器对象是this。
7、多线程下的单例:
public class Single {
private static Single s=null;
private Single(){}
public static Single getInstance(){
if (s==null) {
synchronized (Single.class) {
if (s==null)
s=new Single();
}
}
return s;
}
}
同步代码块解决了线程安全问题,多加if判断提高了同步带来的效率低问题
8、死锁问题:原因,同步的嵌套。
五、线程间的通讯
概念:多个线程在处理同一资源,任务却不相同。
实例:
public class Resouce {
private String name;
private String sex;
private boolean flag=false;
public synchronized void set(String name,String sex){
if (flag)
try{this.wait();}catch(InterruptedExceptione){e.printStackTrace();}
this.name=name;
this.sex=sex;
this.flag=true;
this.notify();
}
public synchronized void out(){
if (!flag)
try{this.wait();}catch(InterruptedExceptione){e.printStackTrace();}
System.out.println(name+"......."+sex);
this.flag=false;
this.notify();
}
}
public class Input implements Runnable{
Resouce r=null;
public Input(Resouce r) {
this.r=r;
}
public void run() {
int i=0;
while (true) {
if (i==0) {
r.set("大牛", "男");
}else{
r.set("lili", "nv");
}
i=(i+1)%2;
}
}
}
public class Output implements Runnable{
Resouce r=null;
public Output(Resouce r) {
this.r=r;
}
public void run() {
while (true) {
r.out();
}
}
}
public class ResouceDemo {
public static void main(String[] args) {
Resouce r=new Resouce();
new Thread(new Input(r)).start();
new Thread(new Output(r)).start();
}
}
注:等待唤醒机制方法:
1、wait():让线程处于冻结状态,被wait的线程存储于线程池中。
2、notify():唤醒线程池中的任意线程。
3、notifyAll():唤醒线程池中的所有线程。
(这些方法都必须定义在同步中)
六、线程的生命控制
停止线程:通过run()中循环条件的方式结束线程通用
---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Unity开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------