java 线程有两类:
1、用户线程执行结束线程自动关闭
2、守护线程 ,由操作系统或用户创建,独立于jvm
直接调用run()并不能启动新线程,必须要运行start(),执行一系统动作,才会启用新线程。
线程优先级与线程让步通过yield()来实现.当设计多线程程序时,一定不要依赖于线程优先级,因为这是没保证的。
Thread.yield()方法作用是:暂停当前正在执行的线程对象,并执行其它线程。yield()从未导至线程转到待待、睡眠、阻塞状态,yield()争导至线程 从运行状态转到可运行状态,但有可能没效果。
Thread 的非静态方法join(),让一个线程B加到线程A的尾部。在A执行完毕之前B不能工作
同步与锁
java每个对象都有一个内置锁,当程序运行与非静态synchronized同步方法时,自动获得与正在执行代码类的当前实例(this)有关锁,在对象上锁定。释放锁是指线程退出synchronized()块。关于锁与对象:
1、只能同步方法,不能同步类与变量。
2、每个对象只有一个锁。
3、线程睡眠时,当持有的所有锁都不会释放
4、同步损害并发,应该尽量宿小使用范围
要 同步静态方法,需要一个用于整个类的同步锁
public static synchronized int setName(String vname){
xx.name=vname;
}
等同于
public static int setName(String vname){
synchronized (XXX.class){
xx.name=vname;
}
}
如果线程试图进入同步锁,而其锁被占用,则线程在该对象上被阻塞。
何时需要同步
在多线程访问互斥数据时,则需要需要同步以保护数据。
死锁
当两个线程被阻塞,每个线程在等待另一个线程时,就发生死锁。
线程的交互
java.lang.Object对象的
void notify() 呼醒在此对象上等待的单个线程
void notifyAll() 呼醒在此对象上等待的所有线程
void wait() 使当前线程等待,等待其它线程调此对象的notify或notifyall
例子
package stud.com.peidw;
public class ThreadB extends Thread{
int total;
public void run(){
synchronized(this){
for(int i=1;i<101;i++){
total=total+1;
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
notify();
}
}
}
package stud.com.peidw;
public class ThreadA {
public static void main(String[] args) {
// TODO Auto-generated method stub
ThreadB b=new ThreadB();
b.start();
synchronized(b){
System.out.println("等待对象b计算完成...");
try {
b.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("总和:"+b.total);
}
}
java线程调度---休眠
java线程调度---优先级
java线程调度---让步
java线程调度---合并 用join
java线程调度---守护线程
线程启动用,调用setDaemon(boolean on) 把该线程标记录守护线程或用户线程。为true 标志为守护线程。
前台线程执行完,程序退出,不管守护线程的状态。
java线程调度---同步
线程同步是保证多线程安全访问竞争资源的唯 一方法。对于同步,在具体java代码里:
把竞争资源标识为private
同步那些修改资源的代码,使用synchronized,线程同步例子。
package stud.com.peidw;
import stud.com.peidw.beans.User;
public class TestCash {
public static void main(String[] args) {
// TODO Auto-generated method stub
User user=new User("裴", 100);
MyCashThread t1=new MyCashThread("线程A",user,20);
MyCashThread t2=new MyCashThread("线程B",user,-60);
MyCashThread t3=new MyCashThread("线程C",user,40);
MyCashThread t4=new MyCashThread("线程D",user,45);
MyCashThread t5=new MyCashThread("线程E",user,-20);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
package stud.com.peidw;
import stud.com.peidw.beans.User;
public class MyCashThread extends Thread{
private User user;
private int y=0;
public MyCashThread(String name,User u,int y){
super(name);
this.user=u;
this.y=y;
}
public void run(){
user.oper(y);
}
}
package stud.com.peidw.beans;
public class User {
private String code;
private int cash;
public User(String vcode,int vcase){
this.code=vcode;
this.cash=vcase;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public synchronized void oper(int x){
try{
Thread.sleep(1000L);
this.cash+=x;
System.out.println(Thread.currentThread().getName()+"运行结束,增加 "+x+",当前余额 为:"+cash);
Thread.sleep(1000L);
}catch(Exception e){
e.printStackTrace();
}
}
public String toString(){
return "code="+code+",cash="+cash;
}
}
同步方法中,还可以可以使用特定的方法对线程进行调度,如notify,notifyall,wait
java 5 线程池
线程池说白了就是对象池的思想,开辟一块内存空间,里面存放众多未死线程。池中线程的执行调度由池管理器来处理。java5 线程池有多种,分为固定尺寸线程池,可变尺寸线程池。
package stud.com.peidw;
import java.util.concurrent.*;
public class FixThreadDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
//ExecutorService pool=Executors.newFixedThreadPool(2); // 固定线程池
//ExecutorService pool=Executors.newSingleThreadExecutor(); //单线程池
//ExecutorService pool=Executors.newCachedThreadPool(); //可变尺寸线程池
ScheduledExecutorService pool=Executors.newScheduledThreadPool(5); //延时线程池
MyThread1 t1=new MyThread1();
MyThread1 t2=new MyThread1();
MyThread1 t3=new MyThread1();
MyThread1 t4=new MyThread1();
MyThread1 t5=new MyThread1();
MyThread1 t6=new MyThread1();
MyThread1 t7=new MyThread1();
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);
pool.schedule(t6,10,TimeUnit.MILLISECONDS);
pool.schedule(t7,10,TimeUnit.MILLISECONDS);
pool.shutdown();
}
}
class MyThread1 extends Thread{
@Override
public void run(){
System.out.println("正在执行:"+Thread.currentThread().getName());
}
}
自定义线程池:
package stud.com.peidw;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class CustomThreadPool {
public static void main(String[] args) {
// TODO Auto-generated method stub
BlockingQueue<Runnable> bqueue=new ArrayBlockingQueue<Runnable>(20);
ThreadPoolExecutor pool=new ThreadPoolExecutor(2,3,2,TimeUnit.MILLISECONDS,bqueue);
MyThread2 t1=new MyThread2();
MyThread2 t2=new MyThread2();
MyThread2 t3=new MyThread2();
MyThread2 t4=new MyThread2();
MyThread2 t5=new MyThread2();
MyThread2 t6=new MyThread2();
MyThread2 t7=new MyThread2();
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);
pool.execute(t6);
pool.execute(t7);
pool.shutdown();
}
}
class MyThread2 extends Thread{
@Override
public void run(){
System.out.println("正在执行:"+Thread.currentThread().getName());
}
}
有返回值的线程
要想让线程有返回值,需要实现Callable接口,执行 Callable任务后,可以获取一个Future的对象,该对象上get就可以取到Callable返回的对象。
package stud.com.peidw;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class CallableDemo {
public static void main(String[] args) throws Exception, ExecutionException {
// TODO Auto-generated method stub
ExecutorService pool= Executors.newFixedThreadPool(2);
Callable c1=new MyCallable("c1");
Callable c2=new MyCallable("c2");
Future f1=pool.submit(c1);
Future f2=pool.submit(c2);
System.out.println(f1.get().toString());
pool.shutdown();
}
}
class MyCallable implements Callable{
private String old;
public MyCallable(String vold){
this.old =vold;
}
@Override
public Object call() throws Exception {
return old+"任务返回的内容";
}
}
java 5线程锁
package stud.com.peidw;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockDemo {
public static void main(String[] args) {
MyCount myCount=new MyCount("95599000001",4440);//并发访问的账户
Lock lock=new ReentrantLock();
ExecutorService pool=Executors.newCachedThreadPool();
XUser u1=new XUser("裴一",myCount,-440,lock);
XUser u2=new XUser("裴二",myCount,1000,lock);
XUser u3=new XUser("裴三",myCount,2000,lock);
pool.execute(u1);
pool.execute(u2);
pool.execute(u3);
}
}
class XUser implements Runnable{
private String name;
private MyCount myCount;
private int iocash;
private Lock myLock;
public XUser(String name,MyCount myCount,int iocash,Lock mylogck){
this.name=name;
this.myCount=myCount;
this.iocash=iocash;
this.myLock=mylogck;
}
@Override
public void run() {
myLock.lock();
System.out.println(name+"正在操作"+myCount+"账户,金额为"+iocash+",当前金额为"+myCount.getCash());
myCount.setCash(myCount.getCash()+iocash);
System.out.println(name+"操作"+myCount+"账户成功,金额为"+iocash+",当前金额为"+myCount.getCash());
myLock.unlock();
}
}
class MyCount{
private String oid;
private int cash;
public MyCount(String oid,int cash){
this.oid=oid;
this.cash=cash;
}
public String getOid() {
return oid;
}
public void setOid(String oid) {
this.oid = oid;
}
public int getCash() {
return cash;
}
public void setCash(int cash) {
this.cash = cash;
}
public String toString(){
return "MyCount{oid="+oid+" , cash="+cash+"}";
}
}
阻塞队列
package stud.com.peidw;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class BlockingQueueDemo {
public static void main(String[] args) throws InterruptedException {
BlockingQueue bqueue=new ArrayBlockingQueue(20);
for (int i=0;i<30;i++){
bqueue.put(i);
System.out.println("向队例中加入:"+i+"无素");
}
System.out.println("程序结束");
}
}