JAVA---线程


什么是线程?

线程是一个程序里的不同执行路径

一般的程序是从一个入口出发,沿着唯一的路径走到终点,而线程则使唯一的路径变成多条路径

以下是单线程操作

class A extends Thread
{
	public void run()
	{
		while(true)
		{
			System.out.println("hello world");
		}
	}
}
public class Thread1 {
	public static void main(String[]args)
	{
		A aa=new A();
		aa.run();
		while(true)
		{
			System.out.println("hello JAVA");
		}
	}
}
因为aa.run没有执行完毕,下面的while循环就不会执行,所以就是一直输出“hello world“

再看看多线程操作

class A extends Thread
{
	public void run()
	{
		while(true)
		{
			System.out.println("hello world");
		}
	}
}
public class Thread1 {
	public static void main(String[]args)
	{
		A aa=new A();
		aa.start();
		while(true)
		{
			System.out.println("hello JAVA");
		}
	}
}

Thread中的start方法就是创建一个线程,并且自动调用run方法,直接调用run方法是不会创建一个线程的。

执行一个线程,其实就是执行一个线程里面的run方法,一个Thread对象不能调用两次start方法,否则会抛出异常。

把aa.run改成aa.start结果就是两个循环交替执行,这就是多线程。

单线程就是一条路径,从头到尾执行。

多线程就是有多条路径,每次都可以走不同的路径。

执行aa.start并不代表aa对象的线程就立刻执行,而是得到了能够被CPU执行的资格,也就是就绪的状态。!

创建线程的第二种方式:

class A implements Runnable
{
	public void run()
	{
		while(true)
		{
			System.out.println("hello world");
		}
	}
}
public class Thread2 {
	public static void main(String[]args)
	{
		A aa=new A();
		Thread th=new Thread(aa);
		th.start();
		while(true)
		{
			System.out.println("hello JAVA");
		}
	}
}

Thread常用方法:

setName(String)设置名字

currentThread()返回正在执行线程的对象

getName()返回线程的名字


class A extends Thread
{
    public void run()
    {
            System.out.println("hello world");
            System.out.println(Thread.currentThread().getName());

    }
}
public class Thread1 
{
    public static void main(String[]args)
    {
        A aa=new A();
        aa.start();
        System.out.println("hello JAVA");
        System.out.println(Thread.currentThread().getName());
    }
}



class A extends Thread
{
	public void run()
	{
			System.out.println("hello world");
			System.out.println(Thread.currentThread().getName());
	}
}
public class Thread1 {
	public static void main(String[]args)
	{
		A aa=new A();
		aa.setName("123");
		aa.start();
		System.out.println("hello JAVA");
		System.out.println(Thread.currentThread().getName());
	}
}

Thread的sleep方法
sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。
要捕获异常!

class A extends Thread
{
	public void run()
	{
			for(int i=0;i<10;i++)
			{
				System.out.println(Thread.currentThread().getName()+i);
				try{
					Thread.sleep(1000);
				}
				catch(Exception e)
				{
					e.printStackTrace();
				}
			}
	}
}
public class Thread1 {
	public static void main(String[]args)
	{
		A aa=new A();
		aa.start();
	}
}

Thread的join方法:如a.join();暂停当前正在执行的线程,直到a的线程运行终止之后当前线程才有机会得到执行,注意:不是暂停a对象的线程,而是当前运行的线程

class A extends Thread
{
	public void run()
	{
			for(int i=0;i<10;i++)
			{
				System.out.println(Thread.currentThread().getName()+i);
			}
	}
}
public class Thread1 {
	public static void main(String[]args)
	{
		A aa=new A();
		aa.start();
		try{
			aa.join();
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		for(int i=0;i<10;i++)
		{
			System.out.println(Thread.currentThread().getName()+i);
		}
	}
}
Thread的优先级:

getPriority:获取优先级

setPriority:设置优先级

Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程。

线程调度器用数字表现,范围从一到十,一个线程默认是5。

通常优先级高的比优先级低的要先执行,但并不是一定的!因为实际开发中并不单纯依赖优先级来决定优先级的运行顺序

class A implements Runnable{
    public void run()
    {
        for(int i=0;i<10;i++)
        {
            System.out.println("A"+i);
        }
    }
}
class B implements Runnable{
    public void run()
    {
        for(int i=0;i<10;i++)
        {
            System.out.println("B"+i);
        }
    }
}
public class Thread3 {
    public static void main(String[]args)
    {
        Thread t1=new Thread(new A());
        Thread t2=new Thread(new B());
        t1.setPriority(Thread.MIN_PRIORITY);
        t2.setPriority(Thread.MAX_PRIORITY);
        t1.start();
        t2.start();
    }
}


优先级越高!越容易被CPU先调用!


线程的同步

卖票系统!

假如有三个地方,A,B,C同时卖票

假如代码写成这样

if(票数大于0)
{
	买票
	票数-1
}

当A发现票大于0的时候,本应该执行下一步,假如此时CPU切换的B线程的时候,发现票数大于0(因为在A线程里面,票数没有减一),当在B中发现票数大于0之后,假如CPU又切换到C线程里面,发现票数还是大于0(同理)假如票只有一张,那么此时就相当于一张票被卖了三次。

这将产生错误!

class A implements Runnable
{
	private int tickets=100;
	public void run()
	{
		while(true)
		{
			if(tickets>0)
			{
				System.out.println(Thread.currentThread().getName()+"正在卖出第"+tickets+"张票");
				tickets--;
			}
			else
			{
				break;
			}
		}
	}
}
public class Thread4 {
	public static void main(String[]args)
	{
		A a=new A();
		Thread t1=new Thread(a);
		t1.start();
		A b=new A();
		Thread t2=new Thread(b);
		t2.start();
	}
}

以上代码运行结果:

每张票都被卖出去两次!!!这是不合理的

导致这个的原因是a对象和b对象都有一个属于自己的tickets 100

那么接下来看以下程序

class A implements Runnable
{
	static int tickets=100;
	public void run()
	{
		while(true)
		{
			if(tickets>0)
			{
				System.out.println(Thread.currentThread().getName()+"正在卖出第"+tickets+"张票");
				tickets--;
			}
			else
			{
				break;
			}
		}
	}
}
public class Thread4 {
	public static void main(String[]args)
	{
		A a=new A();
		Thread t1=new Thread(a);
		t1.start();
		A b=new A();
		Thread t2=new Thread(b);
		t2.start();
	}
}

把票数改成静态的

结果是这样的:


那么来分析一下这个结果是为什么,当Thread-0发现票数是100的时候执行卖出操作,然后立刻切换的线程1然后发现还是100但是没有执行卖出操作又转换为线程0,此时减一然后就变成99、98、97、96、95、这个时候立刻切换成线程1执行卖出操作,打印出来,。

简单来说:CPU会在线程之间来回切换!

好的,重点来了!

Synchronized---同步

class A implements Runnable
{
	static int tickets=100;
	public void run()
	{
		while(true)
		{
			synchronized(this)
			{
				if(tickets>0)
				{
					System.out.println(Thread.currentThread().getName()+"正在卖出第"+tickets+"张票");
					tickets--;
				}
				else
				{
					break;
				}
			}
		}
	}
}
public class Thread4 {
	public static void main(String[]args)
	{
		A a=new A();
		Thread t1=new Thread(a);
		Thread t2=new Thread(a);
		t1.start();
		t2.start();
	}
}
结果如下

synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程(例如线程A),运行到这个方法时,都要检查有没有其它线程B(或者C、 D等)正在用这个方法(或者该类的其他同步方法),有的话要等正在使用synchronized方法的线程B(或者C 、D)运行完这个方法后再运行此线程A,没有的话,锁定调用者,然后直接运行。它包括两种用法:synchronized 方法和 synchronized 块。







猜你喜欢

转载自blog.csdn.net/qq_36457148/article/details/77526935