Java -- 线程
1. 创建线程(一)
定义线程类, 继承Thread 并重写run(), run()称为线程体。
单继承限制,尽量少用。
class firstThread extends Thread {
}
public class main {
}
创建线程(二)
实现接口Runnable, 并将其对象传入 Thread构造函数,生成Thread对象。
class RunnableImpl implements Runnable{
}
public class main {
}
两种方法对比:
继承Thread类: 编写简单,不必使用Thread.currentThread(),直接this.getName()即可。 但是不能再继承其他类了。。
实现Runnable接口: 可再继承其他类,可以多线程共享一个目标对象,但是编写略复杂,访问当前线程需要用Thread.currentThread()。
2. Join 线程等待
public class Main extends Thread{
private int i;
public Main(String name)
{
super(name);
}
public void run()
{
for(; i<100; i++)
{
System.out.println(getName() + " " + i);
}
}
public static void main(String[] args) throws InterruptedException
{
Main thread1 = new Main("1");
Main thread2 = new Main("2");
for(int i=0; i<100; i++)
{
if( i==20 )
{
thread1.start();
thread1.join(); //一直阻塞到线程1结束
thread2.start();
}
}
}
}
3. 后台线程 (守护线程) : JVM垃圾回收线程就是典型的后台线程,如果所有的前台线程都死亡,后台线程会自动死亡。
调用Thread对象的setDaemon(true)则可以设置线程为后台线程。
例如上面的 thread1.setDaemon(true); 即可。。
4. 线程让步 和 优先级设置
使用Thread的静态方法 Thread.yield()即可, 让步后线程并不是进入阻塞态,而是进入就绪态 重新竞争。
设置线程优先级可以用 thread1.setPriority(int ...) ; 输入参数可以为 MAX_PRIORITY 值为10, MIN_PRIORITY 1, NORM_PRIORITY 5.
5. 同步代码块 synchronized
可以使用同步代码块,锁定临界资源 synchronized(Object obj){... ....}
public void run()
{
Integer i;
for(i=0; i<100; i++)
{
synchronized(i) //同步代码块
{
System.out.println(getName() + " " + i);
}
}
}
还可以用synchronized 修饰类的方法,让该方法变为线程安全。
例如 public synchronized void draw() { ... ... }
6. 同步锁 ReadWriteLock(读写锁) ReentrantLock(可重入锁)
class A
{
private final ReentrantLock lock = new ReentrantLock(); //定义锁对象
public void fun()
{
lock.lock(); //加锁
try
{
// 需要 线程安全的代码
}
finally
{
lock.unlock(); //解锁
}
}
}
7.线程通信
利用wait() 当前线程等待 notify()唤醒在同步监视器上等待的单个线程。 notifyAll()唤醒在同步监视器上的所有线程。
class A //属性 num 加一 减一
{
private Boolean putflag = false;
private Integer num = 0;
public synchronized void get()
{
try
{
if( !putflag )
{
wait(); //阻塞
}
else
{
num--;
System.out.println(Thread.currentThread().getName() + " get " + num);
putflag = false;
notifyAll(); //唤醒
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
public synchronized void put()
{
try
{
if( putflag )
{
wait();
}
else
{
num++;
System.out.println(Thread.currentThread().getName() + " put " + num);
putflag = true;
notifyAll();
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
class Get extends Thread
{
private A a;
private String name;
public Get(String name, A a)
{
this.name = name;
this.a = a;
}
public void run()
{
for(int i=0; i<10; i++)
{
System.out.println(name);
a.get(); //减一
}
}
}
class Put extends Thread
{
private A a;
private String name;
public Put(String name,A a)
{
this.name = name;
this.a = a;
}
public void run()
{
for(int i=0; i<10; i++)
{
System.out.println(name);
a.put(); //加一
}
}
}
public class Main extends Thread{
public static void main(String[] args)
{
A a = new A();
new Get("lisi", a).start();
new Put("wangwu", a).start();
new Put("zhangsan", a).start();
}
}
输出效果是 加一 减一 交替进行。
如果不是用synchronized来保证同步的,如果是用lock, 可以用Condition来做协调
如下只需修改Class A
class B
{
private final Lock lock = new ReentrantLock(); //定义一个锁 lock
private final Condition cond = lock.newCondition(); //定义 Condition
public void put()
{
lock.lock();
try
{
if( !flag )
{
cond.await(); //阻塞
}
else
{
.... .....
cond.signalAll(); //唤醒
}
}
}
}
使用管道线程间通信
管道字节流: PiedInputStream PieOutputStream 管道字符流: PipedReader PipedWriter 新IO管道Channel: Pipe.SinkChannel PipeSourceChannel
class ReaderThread extends Thread
{
private PipedReader pr; //输入管道
private BufferedReader br;
public ReaderThread(PipedReader pr)
{
this.pr = pr;
this.br = new BufferedReader(pr);
}
public void run()
{
String buf = null;
try
{
while( (buf=br.readLine()) != null )
{
System.out.println("Reader: " + buf);
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try {
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class WriterThread extends Thread
{
String[] strs = new String[]{ "1234", "5678", "qwer", "asdf" };
private PipedWriter pw; //写管道
public WriterThread(PipedWriter pw)
{
this.pw = pw;
}
public void run()
{
try
{
for(int i=0; i<10; i++)
{
pw.write(strs[i%4] + "\n");
System.out.println("Writer" + strs[i%4]);
}
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
try {
pw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class Main extends Thread{
public static void main(String[] args)
{
PipedReader pr = null;
PipedWriter pw = null;
try
{
pw = new PipedWriter();
pr = new PipedReader();
pw.connect(pr); //管道连接
new WriterThread(pw).start(); //开启读写线程
new ReaderThread(pr).start();
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
浙公网安备 33010602011771号