您的位置:首页 > 编程语言 > Java开发

Java线程学习

2017-05-15 15:16 148 查看
一、创建线程的两种方式:
1、在Thread子类覆盖的run方法编写运行代码,在此处的run方法是属于Thread的子类,所以会优先执行。
Thread thread = new Thread(
@Override
public void run(){
 //线程运行代码
}
);
2、在传递的Runnable对象中的run方法编写运行代码,Runnale里面的run方法是属于Thread父类的run方法,所以当子类中没有覆盖时才会执行。

Thread thread = new Thread(
new Runnable(){

@Override
public void run(){
 //线程运行代码
}

}
);
总结:两者实现方式其实都是调用Thread对象里面的run方法,如果Thread对象里面的run方法没有被覆盖,并且为该对象设置了Runnable对象,则该run方法会调用Runnable对象的run方法。

二、定时器
格式:
Timer timer = new Timer();
timer.schedule( new TimerTask( 重写run方法),Date time//延迟时间,单位s);

三、线程间的互斥与通信
用synchronized关键字来互斥。
用wait和notify来通信。

用Java实现生产者消费者的几种方法:
1、采用synchronized锁以及wait notify方式实现

public class WaitAndNotify
{
public static void main(String[] args) throws IOException
{
Person person = new Person();
new Thread(new Consumer("消费者一", person)).start();
new Thread(new Consumer("消费者二", person)).start();
new Thread(new Consumer("消费者三", person)).start();

new Thread(new Producer("生产者一", person)).start();
new Thread(new Producer("生产者一", person)).start();
new Thread(new Producer("生产者一", person)).start();

}
}

class Producer implements Runnable
{
private Person person;
private String producerName;

public Producer(String producerName, Person person)
{
this.producerName = producerName;
this.person = person;
}

@Override
public void run()
{
while (true)
{
try
{
person.produce();
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}

}

class Consumer implements Runnable
{

private Person person;
private String consumerName;

public Consumer(String consumerName, Person person)
{
this.consumerName = consumerName;
this.person = person;
}

@Override
public void run()
{
try
{
person.consume();
} catch (InterruptedException e)
{
e.printStackTrace();
}

}

}

class Person
{
private int foodNum = 0;
private Object synObj = new Object();

private final int MAX_NUM = 5;

public void produce() throws InterruptedException
{
synchronized (synObj)
{
while (foodNum == 5)
{
System.out.println("box is full,size = " + foodNum);
synObj.wait();
}
foodNum++;
System.out.println("produce success foodNum = " + foodNum);
synObj.notifyAll();
}

}

public void consume() throws InterruptedException
{
synchronized (synObj)
{
while (foodNum == 0)
{
System.out.println("box is empty,size = " + foodNum);
synObj.wait();
}
foodNum--;
System.out.println("consume success foodNum = " + foodNum);
synObj.notifyAll();
}

}
}

2、采用Lock锁以及await和signal方法是实现

public class AwaitAndSignal
{
public static void main(String[] args) throws IOException
{
Person person = new Person();
new Thread(new Consumer(person), "消费者一").start();
new Thread(new Consumer(person), "消费者二").start();
new Thread(new Consumer(person), "消费者三").start();

new Thread(new Producer(person), "生产者一").start();
new Thread(new Producer(person), "生产者一").start();
new Thread(new Producer(person), "生产者一").start();
}
}

class Producer implements Runnable
{
private Person person;

public Producer(Person person)
{
this.person = person;
}

@Override
public void run()
{

for (int i = 0; i < 10; i++)
{
person.produce();
}

}

}

class Consumer implements Runnable
{

private Person person;

public Consumer(Person person)
{
this.person = person;
}

@Override
public void run()
{

for (int i = 0; i < 10; i++)
{
person.consume();
}

}

}

class Person
{
private int foodNum = 0;

private ReentrantLock lock = new ReentrantLock();

private Condition condition = lock.newCondition();

private final int MAX_NUM = 5;

public void produce()
{
lock.lock();
try
{
while (foodNum == MAX_NUM)
{
System.out.println("box is full,size = " + foodNum);
condition.await();
}
foodNum++;
System.out.println("produce success foodNum = " + foodNum);
condition.signalAll();
}
catch(InterruptedException e)
{
e.printStackTrace();
} finally
{
lock.unlock();
}

}

public void consume()
{
lock.lock();
try
{
while (foodNum == 0)
{
System.out.println("box is empty,size = " + foodNum);
condition.await();
}
foodNum--;
System.out.println("consume success foodNum = " + foodNum);
condition.signalAll();
}
catch(InterruptedException e)
{
e.printStackTrace();
} finally
{
lock.unlock();
}

}
}

3、采用BlockingQueue实现

public class Producer implements Runnable {
BlockingQueue<String> queue;

public Producer(BlockingQueue<String> queue) {
this.queue = queue;
}

@Override
public void run() {
try {
String temp = "A Product, 生产线程:"
+ Thread.currentThread().getName();
System.out.println("I have made a product:"
+ Thread.currentThread().getName());
queue.put(temp);//如果队列是满的话,会阻塞当前线程
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}

import java.util.concurrent.BlockingQueue;

public class Consumer implements Runnable{
BlockingQueue<String> queue;

public Consumer(BlockingQueue<String> queue){
this.queue = queue;
}

@Override
public void run() {
try {
String temp = queue.take();//如果队列为空,会阻塞当前线程
System.out.println(temp);
} catch (InterruptedException e) {

9d2a
e.printStackTrace();
}
}
}

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class Test3 {

public static void main(String[] args) {
BlockingQueue<String> queue = new LinkedBlockingQueue<String>(2);
// BlockingQueue<String> queue = new LinkedBlockingQueue<String>();
//不设置的话,LinkedBlockingQueue默认大小为Integer.MAX_VALUE

// BlockingQueue<String> queue = new ArrayBlockingQueue<String>(2);

Consumer consumer = new Consumer(queue);
Producer producer = new Producer(queue);
for (int i = 0; i < 5; i++) {
new Thread(producer, "Producer" + (i + 1)).start();

new Thread(consumer, "Consumer" + (i + 1)).start();
}
}
}

扩展:

BlockingQueue有四个具体的实现类,根据不同需求,选择不同的实现类

1、ArrayBlockingQueue:一个由数组支持的有界阻塞队列,规定大小的BlockingQueue,其构造函数必须带一个int参数来指明其大小.其所含的对象是以FIFO(先入先出)顺序排序的。

2、LinkedBlockingQueue:大小不定的BlockingQueue,若其构造函数带一个规定大小的参数,生成的BlockingQueue有大小限制,若不带大小参数,所生成的BlockingQueue的大小由Integer.MAX_VALUE来决定.其所含的对象是以FIFO(先入先出)顺序排序的。

3、PriorityBlockingQueue:类似于LinkedBlockQueue,但其所含对象的排序不是FIFO,而是依据对象的自然排序顺序或者是构造函数的Comparator决定的顺序。

4、SynchronousQueue:特殊的BlockingQueue,对其的操作必须是放和取交替完成的。
LinkedBlockingQueue 可以指定容量,也可以不指定,不指定的话,默认最大是Integer.MAX_VALUE,其中主要用到put和take方法,put方法在队列满的时候会阻塞直到有队列成员被消费,take方法在队列空的时候会阻塞,直到有队列成员被放进来。

四、ThreadLocal实现线程范围内的共享变量
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息