线程,定时任务

1. 线程的状态
  1) NEW: 线程刚创建。
  2) RUNNABLE: 可执行的或正在执行的线程所处的状态。
  3) TERMINATED: 已退出的线程。
  4) BLOCKED: 受阻塞并等待某个监视器锁的线程所处的状态。
  5) WAITING: 等待状态。
  6) TIMED WAITING: 超时等待状态。

例1:

package com.wx;
/**
 * @author wx
 *  线程的睡眠
 */
public class Test1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread t=new Thread(new MyThread1());
t.start();
}
}

class MyThread1 implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<10;i++){
System.out.println(i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

例2:

package com.wx;
/**
 * @author wx
 * 线程的让步
 */
public class Test2 {

public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("主线程");
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"-->"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

Thread t1=new Thread(new MyThread2());
t1.setName("线程一:");
t1.start();

Thread t2=new Thread(new MyThread2());
t2.setName("线程二:");
t2.start();
}
}

class MyThread2 implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<10;i++){
if(i==5){
Thread.yield();
}
System.out.println(Thread.currentThread().getName()+"->"+i);
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

//class MyThread3 implements Runnable{
//
// @Override
// public void run() {
// // TODO Auto-generated method stub
// for(int i=0;i<10;i++){
// if(i==5){
// Thread.yield();
// }
// System.out.println(Thread.currentThread().getName()+"->"+i);
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// }
// }
//}

例3:

package com.wx;
/**
 * @author wx
 * 线程的加入
 */
public class Test3 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread t1=new Thread(new MyThread3());
t1.setName("线程一:");
t1.start();
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"->"+i);
if(i==5){
try {
t1.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
class MyThread3 implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<10;i++){

System.out.println(Thread.currentThread().getName()+"->"+i);
}
}
}


☆2. 线程状态的转换:
  1) RUNNABLE --> BLOCKED: 当前线程要操作的资源被其它线程锁定。
     BLOCKED --> RUNNABLE: 当要操作的资源上的同步锁被释放了。
  2) RUNNABLE --> WAITING: 
     当前线程中调用了某个Object的wait()方法,让本线程进入WAITING状态。
     当前线程中调用了另一个线程的join()方法,当前线程进入WAITING状态。
     WAITING  --> RUNNABLE:
     在某个线程中调用对应Object的notify(),notifyAll()方法时,等待在这个Object对象上的线程就会进入RUNNABLE。
     那个join进来的线程执行完毕时,当前线程会进入RUNNABLE。
  3) RUNNABLE --> TIMED WAITING: 
     当前线程中调用了某个Object的wait(long time)方法,让本线程进入TIMED WAITING状态。
     当前线程中调用了sleep(long timeout)方法,当前线程进入TIMED WAITING状态。
     当前线程中调用了其它线程的join(long millis)方法,当前线程进入TIMED WAITING状态。
     TIMED WAITING --> RUNNABLE:
     等待时间已到,调用notify(), notifyAll()。
     睡眠时间结束。
     等待时间已到。


3. 线程的优先级:1~10级。默认是NORM_PRIORITY(5), 最高级别MAX_PRIORITY(10), 最低MIN_PRIORITY(1)
   Thread类提供了setPrority(int level)方法来更改优先级。并不是所有的操作系统都支持线程的优先级。

例1:

package com.wx;
/**
 * @author wx
 *  线程优先级
 */
public class Test4 {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getPriority());
Thread.currentThread().setPriority(10);
Thread t=new Thread(new MyThread4());
t.setName("线程一:");
t.setPriority(10);
System.out.println(t.getPriority());
t.start();
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"--->"+i);
}
System.out.println("主线程执行完毕");
}
}

class MyThread4 implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"--->"+i);
}
}
}

例2:

package com.wx;
/**
 * @author wx
 *  生产者和消费者
 *  
 *  解决问题:
 *   生产者过快消费者会漏掉一部分数据
 *   消费者过快则每次取到的产品都是一样的
 *  
 *  理想的情况:  生产者和消费者保持一致的状态
 */
public class Test5 {
public static void main(String[] args) {
Clerk clerk=new Clerk();
ProductThread pt=new ProductThread(clerk);

SaleThread st=new SaleThread(clerk);

pt.start();
st.start();
}
}
/**
 * 店员
 * @author wx
 *
 */
class Clerk{
private int count;//表示商店存放产品的数量  20
public synchronized void addProduct(){
//如果店铺存放的产品大于20,则通知生产者等一下
if(count>20){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
System.out.println("生产者生产第"+(count+1)+"个产品");
count++;
//唤醒生产者和消费者
notifyAll();
}
}

/**
* 消费,卖产品
*/
public synchronized void salProduct(){
if(count<0){
try {
wait();//让消费者等待
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{

System.out.println("消费者取走第"+(count+1)+"个产品");
count--;
notifyAll();//生产者+消费者
}
}
}
/**
 * 生产者线程
 * @author wx
 *
 */
class ProductThread extends Thread{
private Clerk clerk;
public ProductThread(Clerk clerk){
this.clerk=clerk;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
try {
Thread.sleep((long)(Math.random()*100));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//调用店铺的addProduct方法,添加产品到商铺
clerk.addProduct();
}
}
}

class SaleThread extends Thread{
private Clerk clerk;
public SaleThread(Clerk clerk){
this.clerk=clerk;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
try {
Thread.sleep((long)(Math.random()*100));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
clerk.salProduct();
}
}
}


★4. 线程的同步:
   1) 如果在run()方法中操作到了成员变量(共享数据),那么就可能会出现线程不同步问题(线程安全问题).
   2) 使用synchronized关键字来解决。   锁的粒度尽量小。。。
      a) 同步块: synchronized(this.getClass()){  操作到成员变量的代码; }
      b) 同步方法:public synchronized void test() { ... }  //应该只锁操作到成员变量的方法
      c) JDK5.0提供了Lock,可以很方便添加到代码中。
         static Lock locker = new ReentrantLock();
         locker.lock();
         ...
         locker.unlock();
   3) 死锁问题:仔细分析,把锁的粒度加大一些。

例:

package com.wx;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
 * @author wx
 *
 */
public class Test6 {
public static void main(String[] args) {
// TODO Auto-generated method stub
List list=new ArrayList();
synchronized (list) {
}
List list2=Collections.synchronizedList(new ArrayList());
synchronized (list2) {

}
}
}   


   4)多线程安全问题
    当run()方法体内的代码操作到了成员变量(共享数据)时,就可能会出现多线程安全问题(线程不同步问题)。


编程技巧
在方法中尽量少操作成员变量,多使用局部变量
   

5. 线程间的交互:Object提供的wait(), notify(), notifyAll()。 生产者消费者问题。


6.容器类线程安全问题
容器类大多数默认都没有考虑线程安全问题,程序必须自行实现同步以确保共享数据在多线程下存取不会出错:
可以用synchronized来锁住这个对象
   synchronized(list){   list.add(…);    }
可以使用java.uitl.Collections的synchronizedXXX()方法来返回一个同步化的容器对象
List list = Collections.synchronizedList(new ArrayList());
这种方式在迭代时仍要用synchronized修饰

JDK5.0之后,新增了java.util.concurrent这个包,其中包括了一些确保线程安全的容器类,
如ConcurrentHashMap、CopyOnWriteArrayList、CopyOnWriteArraySet,
它们在效率与安全性上取得了较好的平衡。


6. 定时任务:
  1) java.util.Timer 计时器类

  2) java.util.TimerTask 任务类

例1:

package com.wx;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;
/**
 * @author wx
 *  Timer定时器
 */
public class Test7 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Timer t=new Timer();
//t.schedule(new MyTimerTask(), 1000L, 2000L);
//t.schedule(new MyTimerTask(), new Date());
//t.schedule(new MyTimerTask(), new Date(), 1000L);
//t.scheduleAtFixedRate(new MyTimerTask(), 1000L, 2000L);
//t.scheduleAtFixedRate(new MyTimerTask(), new Date(), 2000L);
String str="2014-09-12 16:00:00";
SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
Date date=format.parse(str);
//t.scheduleAtFixedRate(new MyTimerTask(), date, 2000L);
t.schedule(new MyTimerTask(), date, 2000L);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
boolean flag=true;
while(flag){
try {
int ch=System.in.read();
if(ch=='e'){
t.cancel();
flag=false;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("任务完成!!!")
}
}

class MyTimerTask extends TimerTask{
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("猪起床了...");
}
}
例2:

package com.wx;
/**
 * @author wx
 *用程序模拟铁路售票系统:实现通过四个售票点发售某日某次列车的1000张车票,一个售票点用一个线程表示。
 */
public class Test10 {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyTickets my=new MyTickets();
//创建四个窗口
Thread t1=new Thread(my);
t1.setName("窗口一:");
t1.start();
Thread t2=new Thread(my);
t2.setName("窗口二:");
t2.start();
Thread t3=new Thread(my);
t3.setName("窗口三:");
t3.start();
Thread t4=new Thread(my);
t4.setName("窗口四:");
t4.start();
}
}

class MyTickets implements Runnable{
int count=0;
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
if(count<100){
System.out.println(Thread.currentThread().getName()+"正在卖出第"+(count+1)+"票");
count++;
}else{
break;
}
}
}
}

例3:

package com.wx;
/**
 * @author wx
 *用程序模拟铁路售票系统:实现通过四个售票点发售某日某次列车的1000张车票,一个售票点用一个线程表示。
  同步代码块
 */
public class Test11 {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyTickets2 my=new MyTickets2();
//创建四个窗口
Thread t1=new Thread(my);
t1.setName("窗口一:");
t1.start();
Thread t2=new Thread(my);
t2.setName("窗口二:");
t2.start();
Thread t3=new Thread(my);
t3.setName("窗口三:");
t3.start();
Thread t4=new Thread(my);
t4.setName("窗口四:");
t4.start();
}
}

class MyTickets2 implements Runnable{
int count=0;
@Override
public  void run() {
// TODO Auto-generated method stub
while(true){
synchronized (this) {
if(count<100){
System.out.println(Thread.currentThread().getName()+"正在卖出第"+(count+1)+"票");
count++;
}else{
break;
}
}
}
}
}
例4:

package com.wx;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
 * @author lw
 *用程序模拟铁路售票系统:实现通过四个售票点发售某日某次列车的1000张车票,一个售票点用一个线程表示。
  显示加锁
 */
public class Test12 {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyTickets3 my=new MyTickets3();
//创建四个窗口
Thread t1=new Thread(my);
t1.setName("窗口一:");
t1.start();
Thread t2=new Thread(my);
t2.setName("窗口二:");
t2.start();
Thread t3=new Thread(my);
t3.setName("窗口三:");
t3.start();
Thread t4=new Thread(my);
t4.setName("窗口四:");
t4.start();
}
}

class MyTickets3 implements Runnable{
private Lock lock=new ReentrantLock();//获取锁的对象
int count=0;
@Override
public void run() {
// TODO Auto-generated method stub

while(true){
lock.lock();//加锁
if(count<100){
System.out.println(Thread.currentThread().getName()+"正在卖出第"+(count+1)+"票");
count++;
}else{
break;
}
lock.unlock();//解锁

}
}
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章