-------android培训,java培训、期待与您交流! ----------
何谓多线程? 在一个程序中,这些独立运行的程序片断叫作“线程”(Thread),利用它编程的概念就叫作“多线程处理”。多线程处理一个常见的例子就是用户界面。利用线程,用户可按下一个按钮,然后程序会立即作出响应,而不是让用户等待程序完成了当前任务以后才开始响应。
在谈多线程之前,我们先来了解一下,什么叫做"并发",什么叫做"并行",什么叫做异步,什么叫做同步。并发和并行是即相似又有区别的两个概念,并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔内发生。在多道程序环境下,并发性是指在一段时间内宏观上有多个程序在同时运行,但在单CPU计算机系统中,每一时刻却仅能有一道程序执行,故微观上这些程序只能是分时地交替执行。倘若在计算机中有多个CPU处理,则这些可以并发执行的程序便可被分配到多个处理机上,实现并行执行,即利用每个处理机来处理一个可并发执行的程序,这样,多个程序便可以同时执行。至于同步就是 A,B 两个进程并发访问一个对象,为了让A线程执行操作对象时,并不让B线程访问操作对象,为了达到这个目的,java引入了一个监视器机制,即为,当A线程执行时,监视器获得锁,此时B线程无法访问对象,需要等当前访问对象的A线程操作完释放锁后,才可以运行。反之,异步则是没有这个监视器和线程锁,A,B进程可以并行异步访问该对象
所以,我的个人的狭义理解,并发也可以理解为同步,并行则可以理解为异步,下面我写一段并发访问的代码说明多线程的同步问题。
java中,如果需要自己写线程类,有2种方式。
1.继承Thread类,重写run方法。然后调用,不过由于java单继承,多实现的关系,推荐使用下一种实现方法
2.实现Runnable接口,重现run方法,然后在主函数中new Thread的含有Runnable的构造方法,将实例化线程对象传入,并调用Thread的start()方法。
同步线程:java中同步线程的方式有,用Object监视器对象,加synchronized同步方法,和Lock与Condition监视器对象。而是Condition
将 Object
监视器方法(wait,notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock
替代了 synchronized
方法和语句的使用,Condition
替代了 Object 监视器方法的使用,所以我的代码里使用的同步方法是Lock 和Condition
以下是一个产品从生产者到消费者,每生产一次,消费一次,然后再次循环的一个过程。从这个例子,就可以理解java中的多线程同步问题,至于多线程异步,只需要将Lock 和 condition相应的代码块去掉,就可以了,不过在这个例子中,如果多线程异步并行访问,可能会造成一些问题,那就是生产完1次产品,可能这一个产品被消费了2次。所以在这个例子中,考虑到安全性问题,多线程需要同步访问,因为有共享的数据。所以说,如果没有共享的数据,就不需要同步了。异步执行速度反而会高效一些。
package test;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestLock {
public static void main(String[] args) {
//创建产品对象,制造者和消费者,以及对应的线程对象,然后调用start()方法启动
ProductLock pro = new ProductLock();
MadingLock mad = new MadingLock(pro);
SaleLock sale = new SaleLock(pro);
Thread t1 = new Thread(mad);
Thread t2 = new Thread(sale);
t1.start();
t2.start();
}
}
产品对象,分别有名称,产品初始化数量,boolean变量产品是否销售,线程锁,Lock,以及生产及销售的Condition对象,还有set(String name)制造方法,及销售方法,可以在方法里看到,调用线程锁,然后根据产品是否销售完成,分别调用对应的等待方法,等到销售或者生产完毕后将boolean变量转换,并唤起对方线程。
class ProductLock {
private String name;
private int count = 1;
boolean b = false;
private Lock lock = new ReentrantLock();
private Condition made_con =lock.newCondition();
private Condition sale_con =lock.newCondition();
public void set(String name) throws InterruptedException {
try {
lock.lock();
while(b)
made_con.await();
this.name = name + count++;
System.out.println(Thread.currentThread().getName() + "生产者---"+ this.name);
b = true;
sale_con.signal();
}finally{
lock.unlock();
}
}
public void out() throws InterruptedException {
try {
lock.lock();
while (!b)
sale_con.await();
System.out.println(Thread.currentThread().getName() + "消费者------"+ this.name);
b = false;
made_con.signal();
} finally{
lock.unlock();
}
}
}
制造和销售对象,分别循环调用产品的对应方法。
class MadingLock implements Runnable {
private ProductLock pro;
public MadingLock(ProductLock pro) {
this.pro = pro;
}
@Override
public void run() {
while (true) {
try {
pro.set("+商品+");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class SaleLock implements Runnable {
private ProductLock pro;
public SaleLock(ProductLock pro) {
this.pro = pro;
}
@Override
public void run() {
while (true) {
try {
pro.out();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}