您的位置:首页 > 其它

多线程

2015-06-25 23:00 393 查看
(一)、进程、线程、多进程的概念

进程:是一个正在执行中的程序。每一个进程执行都有一个执行顺序。该顺序是一个执行路径,或者叫一个控制单元。

线程:就是进程中的一个独立的控制单元。线程在控制着进程的执行。

注意点:

1、一个进程中至少有一个线程。

2、一个进程中可以有多个执行路径,称之为多线程。

3、开启多个线程是为了同时运行多部分代码,每一个线程都有自己运行的内容,这个内容可以称为线程要执行的任务。

多线程的好处:解决了多部分代码同时运行的问题。

多线程的弊端:线程太多,会导致效率的降低。

什么是”并行”和”并发”:

1.”并行”是指逻辑上一起在执行,它强调的是在”同一段时间内”一起运行的程序;

2.”并发”是指物理上的抢占同一资源。它强调的是在”同一时刻时”一起抢占系统的某个共享资源;

(二)、线程的创建方式

创建线程方式一:继承Thread类

1. 定义一个类继承Thread类。

2. 覆盖Thread类中的run方法。

3. 直接创建Thread的子类对象创建线程。

4. 调用start方法开启线程并调用线程的任务run方法执行。

class Test extends Thread
{
private String name;
public Test(String name)
{
this.name=name;
}
public void run()
{
for (int x=0;x<100 ;x++ )
{
System.out.println((Thread.currentThread()==this)+"----"+this.getName()+"run----"+x);
}
}

}

class ThreadTest
{
public static void main(String[] args)
{
Test t1=new Test("xiaomi");
Test t2=new Test("liming");

t1.start();
t2.start();

for(int x=0;x<100;x++)
{
System.out.println("main------"+x);
}
}
}


创建线程方式二:实现Runnable接口

1. 定义类实现Runnable接口。

2. 覆盖接口中的run方法,将线程的任务代码封装到run方法中。

3. 通过Thread类创建线程对象,并将Runnable接口的子类对象作为Thread类的构造函数的参数进行传递。为什么?因为线程的任务都封装在Runnable接口子类对象的run方法中。所以要在线程对象创建时就必须明确要运行的任务。

4. 调用线程对象的start方法开启线程。

实现Runnable接口的好处:

1. 将线程的任务从线程的子类中分离出来,进行了单独的封装,按照面向对象的思想将任务封装成对象。

2. 避免了Java单继承的局限性。所以,创建线程的第二种方式较为常用。

class Demo implements Runnable{
public void run(){
show();
}
public void show(){
for(int x = 0; x < 100; x++){
System.out.println(Thread.currentThread().getName() + "---" + x);
}
}
}

class ThreadDemo{
public static void main(String[] args){
Demo d = new Demo();
Thread t1 = new Thread(d);
Thread t2 = new Thread(d);
t1.start();
t2.start();
}
}


(三)、线程安全问题

线程安全问题产生的原因?

1. 多个线程在操作共享的数据。

2. 操作共享数据的线程代码有多条。

当一个线程在执行操作共享数据的多条代码过程中,其他线程参与了运算,就会导致线程安全问题的产生。

线程安全问题的解决方案?

将多条操作共享数据的线程代码封装起来,当有线程在执行这些代码的时候,其他线程不可以参与运算。必须要当前线程把这些代码都执行完毕后,其他线程才可以参与运算。

格式有两种:

synchronized(对象){

需要被同步的代码;

}

在函数上加上synchronized修饰符

很好的解决了线程安全问题,但是同步的弊端是当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率。

需求:储户,两个,每个都到银行存钱,每次存100,共存三次。

class Bank{
private int sum ;
public void add(int num){
synchronized(this ){
sum = sum + num;
System. out.println("sum = " + sum);
}
}
}

class Cus implements Runnable{
private Bank b = new Bank();
public void run(){
for(int x = 0; x < 3; x++){
b.add(100);
}
}
}

class BankDemo{
public static void main(String[] args){
Cus c = new Cus();
Thread t1 = new Thread(c);
Thread t2 = new Thread(c);
t1.start();
t2.start();
}
}


(四)、多线程下的单例设计模式

饿汉式

class Single
{
private static final Single s=new Single();
private Single(){}
public static Single getInstance()
{
return s;
}
}


懒汉式

class Single
{
private static Single s=null;
private Single(){}

public static Single getInstance()
{
if(s==null)
{
synchronized(Single.class)
{
if(s==null)
//---->A
s=new Single();
}
}
return s;
}
}


比较:饿汉式不存在安全问题,因为不存在多个线程共同操作数据的情况,懒汉式存在安全问题,可以使用同步函数解决, 但若直接使用同步函数,则效率较低,因为每次都需要判断,需要提前判断以提高效率。

(五)、线程间的通信–生产者和消费者



1. wait():让线程处于冻结状态,被wait的线程会被存储到线程池中。

2. notify():唤醒线程池中的一个线程(任何一个都有可能)。

3. notifyAll():唤醒线程池中的所有线程。

4、wait和sleep区别?

1)wait可以指定时间也可以不指定。sleep必须指定时间。

2)在同步中时,对CPU的执行权和锁的处理不同。

wait:释放执行权,释放锁。

sleep:释放执行权,不释放锁。

多生产着和多消费着问题

class Resource{
private String name ;
private int count = 1;
private boolean flag = false;

public synchronized void set(String name){
while(flag )
try{
this.wait();
} catch(InterruptedException e){
e.printStackTrace();
}
this.name = name + count;
count++;
System.out.println(Thread.currentThread().getName() + "...生产者..." + this. name);
flag = true ;
notifyAll();
}

public synchronized void out(){
while(!flag )
try{
this.wait();
} catch(InterruptedException e){
e.printStackTrace();
}
flag = false ;
notifyAll();
System.out.println(Thread.currentThread().getName() + "...消费者..." + this. name);
}
}

class Producer implements Runnable{
private Resource r ;
Producer(Resource r){
this.r = r;
}
public void run(){
while(true ){
r.set( "馄饨");
}
}
}

class Consumer implements Runnable{
private Resource r ;
Consumer(Resource r){
this.r = r;
}
public void run(){
while(true ){
r.out();
}
}
}

class ProducerConsumerDemo {
public static void main(String[] args){
Resource r = new Resource();
Producer pro = new Producer(r);
Consumer con = new Consumer(r);

Thread t0 = new Thread(pro);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(con);
Thread t3 = new Thread(con);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: