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

java--多线程--线程的操作

2017-09-08 10:33 260 查看
要操作线程就要知道线程的七种状态:

线程的生命周期包含七种状态:

出生状态,就绪状态,运行状态,等待状态,休眠状态,阻塞状态和死亡状态。

使线程处于就绪状态有以下几种方法:

1.调用sleep()方法。

2.调用wait()方法。

3.等待输入/输出完成。

当线程处于就绪状态后。有一下几种方法进行运行:

1.线程调用notity()方法。

2.线程调用notityAll()方法。

3.线程调用interrupt()方法。

4.线程的休眠时间结束。

5.输入/输出结束。

控制线程:使线程从一种状态过渡到另一种状态。

1.线程的休眠。
控制线程休眠调用sleep()方法,sleep()方法需要一个参数用于指定该线程休眠的时间,
该时间以毫秒为单位,它通常是在run()方法内的循环中被使用。

sleep()方法语法:
try{
Thread.sleep(2000);
}catch(Exception e){
e.printStackTrace();
}
这个代码会使线程进入两秒的休眠状态,由于sleep()方法的执行可能抛出InterruptedException异常,所以sleep()方法放入try-catch语句块中。
虽然使用了sleep()方法的线程会自动醒过来,但是醒来后不一定能进入运行状态,只能保证它进入就绪状态。

让线程每过100ms自减一次。

public class Test extends Thread{

int count=0;
public void run(){
while(true){
try{
Thread.sleep(100);
}catch(Exception e){
e.printStackTrace();
}
if(count<100){
System.out.println(count++);
}else{
break;
}
}
}
public static void main(String[] args){
Test t = new Test();
Thread A = new Thread(t);

A.start();
}
}


创建一个不包含停向右滑动的图片窗口

import java.awt.*;
import java.util.*;

import javax.swing.*;
public class SleepMethodTest extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
private Thread t;
// 定义颜色数组
private static Color[] color = { Color.BLACK, Color.BLUE, Color.CYAN,
Color.GREEN, Color.ORANGE, Color.YELLOW, Color.RED,
Color.PINK, Color.LIGHT_GRAY };
private static final Random rand = new Random();// 创建随机对象

private static Color getC() {// 获取随机颜色值的方法
return color[rand.nextInt(color.length)];
}

public SleepMethodTest() {
t = new Thread(new Runnable() {// 创建匿名线程对象
int x = 30;// 定义初始坐标
int y = 50;

public void run() {// 覆盖线程接口方法
while (true) {// 无限循环
try {
Thread.sleep(100);// 线程休眠0.1秒
} catch (InterruptedException e) {
e.printStackTrace();
}
// 获取组件绘图上下文对象
Graphics graphics = getGraphics();
graphics.setColor(getC());// 设置绘图颜色
// 绘制直线并递增垂直坐标
graphics.drawLine(x, y, 100, y++);
if (y >= 80) {
y = 50;
}
}
}
});
t.start();// 启动线程
}

public static void main(String[] args) {
init(new SleepMethodTest(), 100, 100);
}
// 初始化程序界面的方法
public static void init(JFrame frame, int width, int height) {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(width, height);
frame.setVisible(true);
}
}

2.线程的加入
控制线程加入调用join()方法,当某个线程使用join()方法加入到另一个线程时,另一个线程会等待该线程执行完毕后再继续执行。
join()也是放入try-catch语句块中。

定义两个进度条,在进度条B执行完成后让进度条A加入。

import java.awt.*;

import javax.swing.*;

public class JoinTest2 extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
private Thread threadA; // 定义两个线程
private Thread threadB;
final JProgressBar progressBar = new JProgressBar(); // 定义两个进度条组件
final JProgressBar progressBar2 = new JProgressBar();
int count = 0;

public static void main(String[] args) {
init(new JoinTest(), 100, 100);
}

public JoinTest2() {
super();
// 将进度条设置在窗体最
4000
北面
getContentPane().add(progressBar, BorderLayout.NORTH);
// 将进度条设置在窗体最南面
getContentPane().add(progressBar2, BorderLayout.SOUTH);
progressBar.setStringPainted(true); // 设置进度条显示数字字符
progressBar2.setStringPainted(true);
// 使用匿名内部类形式初始化Thread实例子
threadA = new Thread(new Runnable() {
int count = 0;

public void run() { // 重写run()方法
while (true) {
progressBar.setValue(++count); // 设置进度条的当前值
try {
Thread.sleep(100); // 使线程A休眠100毫秒
threadB.join(); // 使线程B调用join()方法
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
threadA.start(); // 启动线程A
threadB = new Thread(new Runnable() {
int count = 0;

public void run() {
while (true) {
progressBar2.setValue(++count); // 设置进度条的当前值
try {
Thread.sleep(100); // 使线程B休眠100毫秒
} catch (Exception e) {
e.printStackTrace();
}
if (count == 100) // 当count变量增长为100时
break; // 跳出循环
}
}
});
threadB.start(); // 启动线程B
}

// 设置窗体各种属性方法
public static void init(JFrame frame, int width, int height) {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(width, height);
frame.setVisible(true);
}
}


3.线程的中断
因为stop()方法在线程中不可控,所以现在在run()方法中使用无限循环的形式,然后使用一个boolean标记来控制循环的停止。
例:
public class InterruptTest{
private boolean isCon = false; //设置一个标记变量,默认值为false。

public void run(){
while(true){
 
....
if(isCon)
break;
//当isCon变量为ture时停止线程
}
}
public void SetCon(){
this.isCon = true;
//定义设置isCon变量为true的方法。
}
}
如果线程是使用了sleep()或wait()方法进入了就绪状态,可以使用Thread类中的interrupt()方法使线程离开run()方法,同时结束线程。
但程序会抛出InterruptException异常,用户可以在处理该异常时完成县城的终端处理。
//线程中断。
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JProgressBar;
public class InterruptedSwing extends JFrame {
Thread thread;
public static void main(String[] args){
init(new InterruptedSwing(),100,100);
}
public InterruptedSwing(){
super();
final JProgressBar proB = new JProgressBar();//创建进度条
getContentPane().add(proB,BorderLayout.NORTH);
proB.setStringPainted(true); //设置进度条上显示数字
thread = new Thread(new Runnable(){
int count = 0;

public void run(){
while(true){
proB.setValue(++count); //设置进度条当前值
try{
thread.sleep(1000);; //使线程休眠1000ms
}catch(InterruptedException e){
System.out.println("当前线程中断");
break;
}
}
}
});
thread.start();
thread.interrupt(); //中断线程。
}
public static void init(JFrame frame,int width,int height){
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(width, height);
frame.setVisible(true);
}
}


4.线程的礼让
使用yield()方法,但它仅仅只是给当下正在运行的线程一个提醒,告诉她可以将资源礼让,但这只是一种暗示,没有任意一种机制保证当前线程资源将资源礼让。

yield()方法使具有同样优先级的线程有进入可以执行的机会,当当前线程防止执行权时会再度回到就绪状态。

5.等待/唤醒机制:

1.wait();  让线程处于冻结状态,释放CPU执行权与执行状态。被wait的线程会被存储到线程池中。

2.notify(); 唤醒线程池中一个线程(任意)

3.notifyAll(); 唤醒线程池中的所有线程,让所有线程拥有执行资格。
class Resource
{
private String name;
private String sex;
private boolean flag=false;
public synchronized void set(String name,String sex)
{
if(flag)
try{
this.wait();
}catch(InterruptedException e){}
this.name=name;
this.sex=sex;
flag=true;
this.notify();
}
public synchronized void out()
{
if(!flag)
try{
this.wait();
}catch(InterruptedException e){}
System.out.println(name+":"+sex);
flag=false;
notify();
}
}

class Input implements Runnable
{
Resource r;
Input(Resource r)
{
this.r=r;
}
public void run()
{
int x=0;
while(true)
{

if(x==0)
{
r.set("test1","c");

}
else
{
r.set("test2","java");
}
x=(x+1)%2;
}

}
}

class output implements Runnable
{
Resource r;
output(Resource r)
{
this.r = r;
}
public void run()
{

while(true)
{
r.out();

}
}
}

class WaitNotifyDemo2
{
public static void main(String[] args)
{   //创建对象
Resource r = new Resource();
//创建资源
Input in =new Input(r);
output out=new output(r);
//创建线程
Thread t1=new Thread(in);
Thread t2=new Thread(out);
//开启线程?
t1.start();
t2.start();

}
}


----------------------------------------------------------------------------------------------------
线程安全:

线程同步机制:
给共享资源加上一道锁,在一个线程访问该资源的时候其他线程只能等待。

1.同步块:
在JAVA中提供了同步机制,可以有效防止资源冲突,同步机制使用synchronized关键字。
将资源放置在同步块中,这个同步块也被称为临界区,它使用synchronize关键字建立,语法如下:
synchronized (object){

}
当其他线程获取到这个锁时,必须等待锁被释放才能进入该区域,Object 为任意一个对象,每个对象都存在一个标志位。,并具有两个值(0、1).
一个线程运行到同步块时首先检查该对象的标志位,如果为0,表明此时有线程在代码块中,这时该线程处于就绪态,等待同步块的锁被释放。
当该对象表示位为1时则执行代码块中代码,同时将Object对象的表示为设置为0;

2.同步方法。
同步方法就是在方法前面修饰synchronized关键字的方法,语法如下:
synchronized void f(){

}

这些方法都必须定义在同步中。

因为这些方法是用于操作线程状态的方法。

必须要明确到底操作的是那个锁上的线程。

为什么操作线程的方法wait notify.notifyAll定义在了object类中。

因为这些方法是监视器的方法,监视器其实就是锁。

锁可以是任意的对象,任意的对象调用的方法一定定义在object类中。

买票问题:避免线程错误

public class ThreadSell implements Runnable{
int num = 20;

public static void main(String[] args){
ThreadSell t = new ThreadSell();
Thread A = new Thread(t);
Thread b = new Thread(t);
Thread C = new Thread(t);
Thread D = new Thread(t);

A.start();
b.start();
C.start();
D.start();

}

public synchronized void doit(){
if(num>0){
try{
Thread.sleep(10);
}catch(Exception e){
e.printStackTrace();
}
System.out.println("tickets: "+--num);
}
}

public void run() {
while(true){
doit();
}
}

}

储户存钱:
class Bank
{
private int sum;
private object obj=new object();
public synchronized void add(int num)//同步函数
{
sum=sum+num;
try{Thread.sleep(10);}catch (InterruptedException e){}//try catch抛出异常
System.ou.println("sum="+sum);

}
}
class Cus implements Runnable
{
private Bank b=new Bank();
public void run()
{

for(int x =0;x<3;x++)
{
b.add(100);
}
}

}
class BankDemo
{
public static void main(String[] args)
{
Cus c =new Cus();
Thread t1=new Thread(c);
Thread t2=new Thread(c);
t1.start();
t2.start();
}
}

生产消费者问题:

Lock接口:替代了同步代码块或同步函数,将同步的隐式锁操作变成显式锁操作

同时更为灵活,可以一个锁上多组监视器。

lock():获取锁

unlock():释放锁,通常需要定义finally代码块中。

Condition接口:出现替代了object中的wait,notify,notifyAll方法

               将这些监视器方法单独进行了封装,变成了condition监视器对象
  可以任意锁进行组合。
   
import java.util.concurrent.locks.*;
class Resource
{
private String name;
private int count =1;
private boolean flag=false;
//创建一个锁对象
Lock lock = new ReentrantLock();
//通过已有的锁获取该锁上的监视器对象
// Condition con = lock.newCondition();
//通过已有的锁获取两组监视器,一组监视生产者,一组监视消费者
Condition pro_con=lock.newCondition();
Condition cos_con=lock.newCondition();

public void set(String name)
{
lock.lock();
try{
while(flag)
try{
pro_con.await();
}catch(InterruptedException e){}
this.name=name+count;
count++;
System.out.println(Thread.currentThread().getName()+"生产者"+this.name);
flag=true;
cos_con.signalAll();
}
finally{
lock.unlock();
}
}
public void out()
{
lock.lock();
try{
while(!flag)
try{
cos_con.await();
}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"...消费者.."+this.name);
flag=false;
pro_con.signalAll();
}
finally{
lock.unlock();
}
}
}
class Producter implements Runnable
{
private Resource r;
Producter(Resource r)
{
this.r=r;
}
public void run()
{
while(true)
{
r.set("Set");

}
}
}

class Custmer implements Runnable
{
private Resource r;
Custmer(Resource r)
{
this.r=r;
}
public void run()
{
while(true)
{
r.out();
}
}
}

class ProducterCustmerDemo
{
public static void main(String[] args)
{ //创建对象
Resource r = new Resource();
//创建资源
Producter in =new Producter(r);
Custmer out=new Custmer(r);
//创建线程
Thread t0=new Thread(in);
Thread t1=new Thread(in);
Thread t2=new Thread(out);
Thread t3=new Thread(out);
//开启线程?
t0.start();
t1.start();
t2.start();
t3.start();

}
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: