1.多线程的创建
多线程有两种创建方式
第一种:
创建一个类继承Thread类来实现
public class Test {
public static void main(String[] args) {
Demo de = new Demo();
de.start();
}
}
class Demo extends Thread{
public void run(){
//重写run方法
}
}
第二种:
创建一个类实现Runnable接口来实现
public class Test {
public static void main(String[] args) {
Demo1 d1 = new Demo1();
Thread th = new Thread(d1);//把实现了Runnable接口的类给Thread让它启动线程
th.start();
}
}
class Demo1 implements Runnable{
public void run() {
//重写run方法
}
}
2.线程的运行状态
3.线程的同步
有两种方式来使线程同步
第一种:
使用
synchronized (对象){
}
代码块来锁定需要同步的代码,这里的锁可以是任何对象,还可以将synchronized 关键字作为一个修饰符来修饰方法,使方法变成同步方法
public synchronized void show(){
}
不过这里的锁将变成this ,当把该方法变为静态方法时,锁将变为类的字节码(类.class)
public static synchronized void show(){
}
第二种:
使用Lock接口
Lock lock = new ReentrantLock();
创建一个Lock接口的子类对象,然后使用lock.lock()方法来加锁和lock.unlock()来解锁
这种方法是显示的,我们可以看见什么时候加锁和什么时候解锁,而synchronized 是隐式的我们是看不到加锁和解锁,而且Lock接口的方法在等待唤醒机制也得到了优化
4.线程之间的通讯
我们用生产者消费者模式的示例来看两种不同模式的线程通讯
第一种:
使用synchronized 关键字进行同步线程之间的通讯
wait()让当前线程等待
<pre name="code" class="java">notifyAll()唤醒所有线程
以上方法都来自Object对象,所以无法直接唤醒想要的线程来执行(因为他会唤醒不必要的线程),因为它只能唤醒所有的线程
示例:
package heima;
public class IntputOutputDome {
/**
* @param args
*/
public static void main(String[] args) {
Res r = new Res();
Thread t1 = new Thread(new Input(r));
Thread t2 = new Thread(new Input(r));
Thread t3 = new Thread(new Output(r));
Thread t4 = new Thread(new Output(r));
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Res{
private String name;
private String sex;
private boolean b = false;
public synchronized void set(String name,String sex){
while(b){
try {
this.wait();//线程等待
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.name=name;
this.sex=sex;
System.out.println(Thread.currentThread().getName()+"......生产......"+name+"----"+sex);
b = true;
this.notifyAll();//唤醒所有线程
}
public synchronized void out(){
while(!b){
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"......消费................."+name +"----"+sex);
b = false;
this.notifyAll();
}
}
class Input implements Runnable{
Res r;
public Input(Res r){
this.r=r;
}
public void run() {
int x = 0;
while(true){
if(x==0){
r.set("张三", "男");
}
else{
r.set("李四", "女");
}
x = (x+1)%2;
}
}
}
class Output implements Runnable{
Res r;
public Output(Res r){
this.r=r;
}
public void run() {
while(true){
r.out();
}
}
}
第二种:
使用Lock接口的线程之间的通讯
await()让当前线程等待
signal()唤醒你想要的线程来执行
<pre name="code" class="java">Lock lock = new ReentrantLock();
Condition c1 = lock.newCondition();
Condition c2 = lock.newCondition();
由Lock接口创建的
多个
Condition 对象,可以用来一个控制消费者的等待唤醒,另一个控制生产者的
等待唤醒,这样就可以避免唤醒了不必要的线程
示例:
package heima;
import java.io.PrintStream;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class IntputOutputDome2 {
/**
* @param args
*/
public static void main(String[] args) {
Res2 r = new Res2();
Thread t1 = new Thread(new Input2(r));
Thread t2 = new Thread(new Input2(r));
Thread t3 = new Thread(new Output2(r));
Thread t4 = new Thread(new Output2(r));
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Res2{
private String name;
private String sex;
private boolean b = false;
private Lock lock = new ReentrantLock();
Condition c1 = lock.newCondition();
Condition c2 = lock.newCondition();
PrintStream out = null;
public void set(String name,String sex){
System.out.println("当前状态:"+b);
lock.lock();//上锁
try {
while(b){
c2.await();
System.out.println("生产:"+Thread.currentThread().getName()+"进入等待");
}
this.name=name;
this.sex=sex;
System.out.println(Thread.currentThread().getName()+"......生产......"+name+"----"+sex);
b = true;
c1.signal();//唤醒其他线程
} catch (Exception e) {
}
finally{
lock.unlock();//解锁
}
}
public void out(){
System.out.println("out当前状态:"+b);
lock.lock();
try {
while(!b){
c1.await();
System.out.println(Thread.currentThread().getName()+"进入等待");
}
System.out.println(Thread.currentThread().getName()+"......消费................."+name +"----"+sex);
b = false;
c2.signal();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
lock.unlock();
}
}
}
class Input2 implements Runnable{
Res2 r;
public Input2(Res2 r){
this.r=r;
}
public void run() {
int x = 0;
while(true){
if(x==0){
r.set("张三", "男");
}
else{
r.set("李四", "女");
}
x = (x+1)%2;
}
}
}
class Output2 implements Runnable{
Res2 r;
public Output2(Res2 r){
this.r=r;
}
public void run() {
while(true){
r.out();
}
}
}