Java多线程总结

一、简介

认识多任务、多进程、单线程、多线程

1、多任务:可以同时干几件事,比如现在你可以即用电脑听歌,写文档

2、多进程:比如mysql数据库,有几个线程分别负责不同的任务

3、单线程:比如第一次学java写的helloworld程序

4、多线程:只有一个进程包含几个线程,比如下载软件

多线程的目的是为了最大限度的利用CPU资源。

5、多线程解决了线程安全问题,每次判断锁,消耗资源

二、线程与进程区别

简单来说,一个进程至少包含一个线程,进程是一个独立的控制单元,线程之间共享内存区,线程间通讯相对容易,而进程却相对困难

三、Java对多线程的实现

注意:Java语言的多线程需要操作系统的支持

1Java中,多线程的实现有两种方式:

扩展java.lang.Thread

实现java.lang.Runnable接口

四、扩展java.lang.Thread类实现多线程

public class TestMitiThread {
    public static void main(String[] rags) {
        System.out.println(Thread.currentThread().getName() + " 线程运行开始!");
        new MitiSay("A").start();
        new MitiSay("B").start();
        System.out.println(Thread.currentThread().getName() + " 线程运行结束!");
    }
}
 
class MitiSay extends Thread {
    public MitiSay(String threadName) {
        super(threadName);
    }
 
    public void run() {
        System.out.println(getName() + " 线程运行开始!");
        for (int i = 0; i < 10; i++) {
            System.out.println(i + " " + getName());
            try {
                sleep((int) Math.random() * 10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(getName() + " 线程运行结束!");
    }
}

总结:

1、在一个方法中调用Thread.currentThread().getName()方法,可以获取当前线程的名字。在mian方法中调用该方法,获取的是主线程的名字。

2、start()方法的调用后并不是立即执行多线程代码,而是使得该线程变为可运行态(Runnable),什么时候运行是由操作系统决定的。

3、Thread.sleep()方法调用目的是不让当前线程独自霸占该进程所获取的CPU资源,以留出一定时间给其他线程执行的机会。

五、实现java.lang.Runnable接口实现多线程

public class TestMitiThread1 implements Runnable {
 
    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName() + " 线程运行开始!");
        TestMitiThread1 test = new TestMitiThread1();
        Thread thread1 = new Thread(test);
        Thread thread2 = new Thread(test);
        thread1.start();
        thread2.start();
        System.out.println(Thread.currentThread().getName() + " 线程运行结束!");
    }
 
    public void run() {
        System.out.println(Thread.currentThread().getName() + " 线程运行开始!");
        for (int i = 0; i < 10; i++) {
            System.out.println(i + " " + Thread.currentThread().getName());
            try {
                Thread.sleep((int) Math.random() * 10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName() + " 线程运行结束!");
    }
}

总结:

1、在启动的多线程的时候,需要先通过Thread类的构造方法Thread(Runnable target) 构造出对象,然后调用Thread对象的start()方法来运行多线程代码。

2、实际上所有的多线程代码都是通过运行Thread的start()方法来运行的。因此,不管是扩展Thread类还是实现Runnable接口来实现多线程,最终还是通过Thread的对象的API来控制线程的,熟悉Thread类的API是进行多线程编程的基础

六、Thread类常用API

static int MAX_PRIORITY

          线程可以具有的最高优先级。

static int MIN_PRIORITY

          线程可以具有的最低优先级。

static int NORM_PRIORITY

          分配给线程的默认优先级。

 

构造方法摘要

Thread(Runnable target)

          分配新的 Thread 对象。

Thread(String name)

          分配新的 Thread 对象。

 

 

方法摘要

static Thread currentThread()

          返回对当前正在执行的线程对象的引用。

 ClassLoader getContextClassLoader()

          返回该线程的上下文 ClassLoader

 long getId()

          返回该线程的标识符。

 String getName()

          返回该线程的名称。

 int getPriority()

          返回线程的优先级。

 Thread.State getState()

          返回该线程的状态。

 ThreadGroup getThreadGroup()

          返回该线程所属的线程组。

static boolean holdsLock(Object obj)

          当且仅当当前线程在指定的对象上保持监视器锁时,才返回 true

 void interrupt()

          中断线程。

static boolean interrupted()

          测试当前线程是否已经中断。

 boolean isAlive()

          测试线程是否处于活动状态。

 boolean isDaemon()

          测试该线程是否为守护线程。

 boolean isInterrupted()

          测试线程是否已经中断。

 void join()

          等待该线程终止。

 void join(long millis)

          等待该线程终止的时间最长为 millis 毫秒。

 void join(long millis, int nanos)

          等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。

 void resume()

          已过时。 该方法只与 suspend() 一起使用,但 suspend() 已经遭到反对,因为它具有死锁倾向。有关更多信息,请参阅为何 Thread.stopThread.suspend 和 Thread.resume 遭到反对?。

 void run()

          如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。

 void setContextClassLoader(ClassLoader cl)

          设置该线程的上下文 ClassLoader

 void setDaemon(boolean on)

          将该线程标记为守护线程或用户线程。

static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)

          设置当线程由于未捕获到异常而突然终止,并且没有为该线程定义其他处理程序时所调用的默认处理程序。

 void setName(String name)

          改变线程名称,使之与参数 name 相同。

 void setPriority(int newPriority)

          更改线程的优先级。

 void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)

          设置该线程由于未捕获到异常而突然终止时调用的处理程序。

static void sleep(long millis)

          在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。

static void sleep(long millis, int nanos)

          在指定的毫秒数加指定的纳秒数内让当前正在执行的线程休眠(暂停执行)。

 void start()

          使该线程开始执行;Java 虚拟机调用该线程的 run 方法。

 void stop()

          已过时。 该方法具有固有的不安全性。用 Thread.stop 来终止线程将释放它已经锁定的所有监视器(作为沿堆栈向上传播的未检查 ThreadDeath 异常的一个自然后果)。如果以前受这些监视器保护的任何对象都处于一种不一致的状态,则损坏的对象将对其他线程可见,这有可能导致任意的行为。stop 的许多使用都应由只修改某些变量以指示目标线程应该停止运行的代码来取代。目标线程应定期检查该变量,并且如果该变量指示它要停止运行,则从其运行方法依次返回。如果目标线程等待很长时间(例如基于一个条件变量),则应使用 interrupt 方法来中断该等待。有关更多信息,请参阅《为何不赞成使用 Thread.stopThread.suspend 和 Thread.resume?》。

 void stop(Throwable obj)

          已过时。 该方法具有固有的不安全性。请参阅 stop() 以获得详细信息。该方法的附加危险是它可用于生成目标线程未准备处理的异常(包括若没有该方法该线程不太可能抛出的已检查的异常)。有关更多信息,请参阅为何 Thread.stopThread.suspend 和 Thread.resume 遭到反对?。

 void suspend()

          已过时。 该方法已经遭到反对,因为它具有固有的死锁倾向。如果目标线程挂起时在保护关键系统资源的监视器上保持有锁,则在目标线程重新开始以前任何线程都不能访问该资源。如果重新开始目标线程的线程想在调用 resume 之前锁定该监视器,则会发生死锁。这类死锁通常会证明自己是“冻结”的进程。有关更多信息,请参阅为何 Thread.stopThread.suspend 和 Thread.resume 遭到反对?。

 String toString()

          返回该线程的字符串表示形式,包括线程名称、优先级和线程组。

static void yield()

          暂停当前正在执行的线程对象,并执行其他线程。

七、线程的状态转换图

线程在一定条件下,状态会发生变化。线程变化的状态转换图如下:


1新建状态(New):新创建了一个线程对象。

2就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。

3运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。

4阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:

(1)等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。

(2)同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM把该线程放入锁。

(3)其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

5死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

八、Java中线程的调度API

Java中关于线程调度的API最主要的有下面几个:

线程睡眠:Thread.sleeplong millis)方法

线程等待:Object类中的wait()方法

线程让步:Thread.yield() 方法

线程加入:join()方法

线程唤醒:Object类中的notify()方法

关于这几个方法的详细应用,可以参考SUNAPI。这里我重点总结一下这几个方法的区别和使用。

sleep方法与wait方法的区别:

sleep方法是静态方法,wait方法是非静态方法。

sleep方法在时间到后会自己“醒来”,但wait不能,必须由其它线程通过notifyAll)方法让它“醒来”。

sleep方法通常用在不需要等待资源情况下的阻塞,像等待线程、数据库连接的情况一般用wait

sleep/waityeld方法的区别:调用sleepwait方法后,线程即进入block状态,而调用yeld方法后,线程进入runnable状态。

waitjoin方法的区别:

wait方法体现了线程之间的互斥关系,而join方法体现了线程之间的同步关系。

wait方法必须由其它线程来解锁,而join方法不需要,只要被等待线程执行完毕,当前线程自动变为就绪。

join方法的一个用途就是让子线程在完成业务逻辑执行之前,主线程一直等待直到所有子线程执行完毕。

-------------------2013-8-27以下------------------------

九、多线程安全

1、同步代码块

/*

通过分析,发现,打印出0,-1,-2等错票。

多线程的运行出现了安全问题。

问题的原因:
	当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,
	另一个线程参与进来执行。导致共享数据的错误。

解决办法:
	对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。



Java对于多线程的安全问题提供了专业的解决方式。

就是同步代码块。

synchronized(对象)
{
	需要被同步的代码

}
对象如同锁。持有锁的线程可以在同步中执行。
没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。

火车上的卫生间---经典。

同步的前提:
1,必须要有两个或者两个以上的线程。
2,必须是多个线程使用同一个锁。

必须保证同步中只能有一个线程在运行。


好处:解决了多线程的安全问题。

弊端:多个线程需要判断锁,较为消耗资源,

*/

class Ticket implements Runnable
{
	private  int tick = 1000;
	Object obj = new Object();
	public void run()
	{
		while(true)
		{
			synchronized(obj)
			{
				if(tick>0)
				{
					//try{Thread.sleep(10);}catch(Exception e){}
					System.out.println(Thread.currentThread().getName()+"....sale : "+ tick--);
				}
			}
		}
	}
}


class  TicketDemo2
{
	public static void main(String[] args) 
	{

		Ticket t = new Ticket();

		Thread t1 = new Thread(t);
		Thread t2 = new Thread(t);
		Thread t3 = new Thread(t);
		Thread t4 = new Thread(t);
		t1.start();
		t2.start();
		t3.start();
		t4.start();


	}
}

总结:

1)持有锁的线程可在同步中执行,没有锁的线程即使有执行全,也进不去,因为没有锁

2)同步的前提:必须要两个或两个以上的线程

2、银行存钱、同步函数

/*
需求:
银行有一个金库。
有两个储户分别存300员,每次存100,存3次。

目的:该程序是否有安全问题,如果有,如何解决?


如何找问题:
1,明确哪些代码是多线程运行代码。
2,明确共享数据。
3,明确多线程运行代码中哪些语句是操作共享数据的。
*/


class Bank
{
	private int sum;
	//Object obj = new Object();
	public synchronized void add(int n) //同步函数
	{
		//synchronized(obj)
		//{
			sum = sum + n;
			try{Thread.sleep(10);}catch(Exception e){}
			System.out.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();
	}
}

3、同步函数锁是this

/*
同步函数用的是哪一个锁呢?
函数需要被对象调用。那么函数都有一个所属对象引用。就是this。
所以同步函数使用的锁是this。

通过该程序进行验证。

使用两个线程来买票。
一个线程在同步代码块中。
一个线程在同步函数中。
都在执行买票动作。



*/
class Ticket implements Runnable
{
	private  int tick = 100;
	Object obj = new Object();
	boolean flag = true;
	public  void run()
	{
		if(flag)
		{
			while(true)
			{
				synchronized(this)
				{
					if(tick>0)
					{
						try{Thread.sleep(10);}catch(Exception e){}
						System.out.println(Thread.currentThread().getName()+"....code : "+ tick--);
					}
				}
			}
		}
		else
			while(true)
				show();
	}
	public synchronized void show()//this
	{
		if(tick>0)
		{
			try{Thread.sleep(10);}catch(Exception e){}
			System.out.println(Thread.currentThread().getName()+"....show.... : "+ tick--);
		}
	}
}


class  ThisLockDemo
{
	public static void main(String[] args) 
	{

		Ticket t = new Ticket();

		Thread t1 = new Thread(t);
		Thread t2 = new Thread(t);
		t1.start();
		try{Thread.sleep(10);}catch(Exception e){}
		t.flag = false;
		t2.start();







//		Thread t3 = new Thread(t);
//		Thread t4 = new Thread(t);
//		t3.start();
//		t4.start();


	}
}

4、静态方法锁该方法所在对象.class

/*
如果同步函数被静态修饰后,使用的锁是什么呢?

通过验证,发现不在是this。因为静态方法中也不可以定义this。

静态进内存是,内存中没有本类对象,但是一定有该类对应的字节码文件对象。
类名.class  该对象的类型是Class


静态的同步方法,使用的锁是该方法所在类的字节码文件对象。 类名.class
*/
class Ticket implements Runnable
{
	private static  int tick = 100;
	//Object obj = new Object();
	boolean flag = true;
	public  void run()
	{
		if(flag)
		{
			while(true)
			{
				synchronized(Ticket.class)
				{
					if(tick>0)
					{
						try{Thread.sleep(10);}catch(Exception e){}
						System.out.println(Thread.currentThread().getName()+"....code : "+ tick--);
					}
				}
			}
		}
		else
			while(true)
				show();
	}
	public static synchronized void show()
	{
		if(tick>0)
		{
			try{Thread.sleep(10);}catch(Exception e){}
			System.out.println(Thread.currentThread().getName()+"....show.... : "+ tick--);
		}
	}
}


class  StaticMethodDemo
{
	public static void main(String[] args) 
	{

		Ticket t = new Ticket();

		Thread t1 = new Thread(t);
		Thread t2 = new Thread(t);
		t1.start();
		try{Thread.sleep(10);}catch(Exception e){}
		t.flag = false;
		t2.start();


	}
}

5、多线程单例

/*
单例设计模式。


*/
//饿汉式。
/*
class Single
{
	private static final Single s = new Single();
	private Single(){}
	public static Single getInstance()
	{
		return s;
	}
}
*/


//懒汉式

class Single
{
	private static Single s = null;
	private Single(){}


	public static  Single getInstance()
	{
		if(s==null)
		{
			synchronized(Single.class)
			{
				if(s==null)
					//--->A;
					s = new Single();
			}
		}
		return s;
	}
}

class SingleDemo 
{
	public static void main(String[] args) 
	{
		System.out.println("Hello World!");
	}
}

6、死锁

1

/*
死锁。
同步中嵌套同步。

*/

class Ticket implements Runnable
{
	private  int tick = 1000;
	Object obj = new Object();
	boolean flag = true;
	public  void run()
	{
		if(flag)
		{
			while(true)
			{
				synchronized(obj)
				{
					show();
				}
			}
		}
		else
			while(true)
				show();
	}
	public synchronized void show()//this
	{
		synchronized(obj)
		{
			if(tick>0)
			{
				try{Thread.sleep(10);}catch(Exception e){}
				System.out.println(Thread.currentThread().getName()+"....code : "+ tick--);
			}
		}
	}
}


class  DeadLockDemo
{
	public static void main(String[] args) 
	{

		Ticket t = new Ticket();

		Thread t1 = new Thread(t);
		Thread t2 = new Thread(t);
		t1.start();
		try{Thread.sleep(10);}catch(Exception e){}
		t.flag = false;
		t2.start();


	}
}

2

class Test implements Runnable
{
	private boolean flag;
	Test(boolean flag)
	{
		this.flag = flag;
	}

	public void run()
	{
		if(flag)
		{
			while(true)
			{
				synchronized(MyLock.locka)
				{
					System.out.println(Thread.currentThread().getName()+"...if locka ");
					synchronized(MyLock.lockb)
					{
						System.out.println(Thread.currentThread().getName()+"..if lockb");					
					}
				}
			}
		}
		else
		{
			while(true)
			{
				synchronized(MyLock.lockb)
				{
					System.out.println(Thread.currentThread().getName()+"..else lockb");
					synchronized(MyLock.locka)
					{
						System.out.println(Thread.currentThread().getName()+".....else locka");
					}
				}
			}
		}
	}
}


class MyLock
{
	static Object locka = new Object();
	static Object lockb = new Object();
}

class  DeadLockTest
{
	public static void main(String[] args) 
	{
		Thread t1 = new Thread(new Test(true));
		Thread t2 = new Thread(new Test(false));
		t1.start();
		t2.start();
	}
}

十、线程通讯

wait:释放资源,释放锁

sleep:释放资源,不释放锁

1、输入输出

/*
线程间通讯:
其实就是多个线程在操作同一个资源,
但是操作的动作不同。

*/
class Res
{
	String name;
	String sex;
	boolean flag = false;
}

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

				if(r.flag)
					try{r.wait();}catch(Exception e){}
				if(x==0)
				{
					r.name="mike";
					r.sex="man";
				}
				else
				{
					r.name="丽丽";
					r.sex = "女女女女女";
				}
				x = (x+1)%2;
				r.flag = true;
				r.notify();
			}
		}
	}
}

class Output implements Runnable
{
	private Res r ;
	
	Output(Res r)
	{
		this.r = r;
	}
	public void run()
	{
		while(true)
		{
			synchronized(r)
			{
				if(!r.flag)
					try{r.wait();}catch(Exception e){}
				System.out.println(r.name+"...."+r.sex);
				r.flag = false;
				r.notify();
			}
		}
	}
}


class  InputOutputDemo
{
	public static void main(String[] args) 
	{
		Res r = new Res();

		Input in = new Input(r);
		Output out = new Output(r);

		Thread t1 = new Thread(in);
		Thread t2 = new Thread(out);

		t1.start();
		t2.start();
	}
}


//notifyAll();

/*
wait:
notify();
notifyAll();

都使用在同步中,因为要对持有监视器(锁)的线程操作。
所以要使用在同步中,因为只有同步才具有锁。

为什么这些操作线程的方法要定义Object类中呢?
因为这些方法在操作同步中线程时,都必须要标识它们所操作线程只有的锁,
只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒。
不可以对不同锁中的线程进行唤醒。

也就是说,等待和唤醒必须是同一个锁。

而锁可以是任意对象,所以可以被任意对象调用的方法定义Object类中。


*/

2、线程唤醒机制

/*
线程间通讯:
其实就是多个线程在操作同一个资源,
但是操作的动作不同。

*/
class Res
{
	private String name;
	private String sex;
	private boolean flag = false;

	public synchronized void set(String name,String sex)
	{
		if(flag)
			try{this.wait();}catch(Exception e){}
		this.name = name;
		
		this.sex = sex;
		flag = true;
		this.notify();
	}
	public synchronized void out()
	{
		if(!flag)
			try{this.wait();}catch(Exception e){}
		System.out.println(name+"........"+sex);
		flag = false;
		this.notify();
	}
}

class Input implements Runnable
{
	private Res r ;
	Input(Res r)
	{
		this.r = r;
	}
	public void run()
	{
		int x = 0;
		while(true)
		{
			if(x==0)				
				r.set("mike","man");				
			else	
				r.set("丽丽","女女女女女");				
			x = (x+1)%2;
		}
	}
}

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


class  InputOutputDemo2
{
	public static void main(String[] args) 
	{
		Res r = new Res();

		new Thread(new Input(r)).start();
		new Thread(new Output(r)).start();
		/*
		Input in = new Input(r);
		Output out = new Output(r);

		Thread t1 = new Thread(in);
		Thread t2 = new Thread(out);

		t1.start();
		t2.start();
		*/
	}
}

3、生产消费者

4、停止线程

Interrupted强制将冻结的线程恢复到运行状态,并抛出InterruptedException异常

/*
stop方法已经过时。

如何停止线程?
只有一种,run方法结束。
开启多线程运行,运行代码通常是循环结构。

只要控制住循环,就可以让run方法结束,也就是线程结束。


特殊情况:
当线程处于了冻结状态。
就不会读取到标记。那么线程就不会结束。

当没有指定的方式让冻结的线程恢复到运行状态是,这时需要对冻结进行清除。
强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。

Thread类提供该方法 interrupt();



*/
class StopThread implements Runnable
{
	private boolean flag =true;
	public  void run()
	{
		while(flag)
		{
			
			System.out.println(Thread.currentThread().getName()+"....run");
		}
	}
	public void changeFlag()
	{
		flag = false;
	}
}




class  StopThreadDemo
{
	public static void main(String[] args) 
	{
		StopThread st = new StopThread();
		
		Thread t1 = new Thread(st);
		Thread t2 = new Thread(st);


		t1.setDaemon(true);
		t2.setDaemon(true);
		t1.start();
		t2.start();

		int num = 0;

		while(true)
		{
			if(num++ == 60)
			{
				//st.changeFlag();
				//t1.interrupt();
				//t2.interrupt();
				break;
			}
			System.out.println(Thread.currentThread().getName()+"......."+num);
		}
		System.out.println("over");
	}
}

5、守护线程或用户线程

void setDaemon(boolean on) 

          将该线程标记为守护线程或用户线程。 启动之前调用

当该线程标记为守护线程时,并且正在运行的都是守护线程。是JVM推出

6、joind方法

 void join() 

          等待该线程终止。 

 void join(long millis) 

          等待该线程终止的时间最长为 millis 毫秒。 

 void join(long millis, int nanos) 

          等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。 

意思:其他线程须等待该线程终止时,其他线程才能交替

  /*
  join:
  当A线程执行到了B线程的.join()方法时,A就会等待。等B线程都执行完,A才会执行。
  
  join可以用来临时加入线程执行。
  
  
  */
  
  class Demo implements Runnable
  {
  	public void run()
  	{
  		for(int x=0; x<70; x++)
  		{
  			System.out.println(Thread.currentThread().toString()+"....."+x);
  			Thread.yield();
  		}
  	}
  }
  
  
  class  JoinDemo
  {
  	public static void main(String[] args) throws Exception
  	{
  		Demo d = new Demo();
  		Thread t1 = new Thread(d);
  		Thread t2 = new Thread(d);
  		t1.start();
  		
  		//t1.setPriority(Thread.MAX_PRIORITY);
  
  		t2.start();
  
  		//t1.join();
  
  		for(int x=0; x<80; x++)
  		{
  			//System.out.println("main....."+x);
  		}
  		System.out.println("over");
  	}
  }

7、优先级

(抢资源的频率)所有线程默认是5,一般用1,5,10

yield方法:暂停当前正在执行的线程对象,并执行其他线程。(相当于只执行一次) 

8、开发中常用线程写法

class ThreadTest 
{
	public static void main(String[] args) 
	{
		
		new Thread()
		{
			public void run()
			{
				for(int x=0; x<100; x++)
				{
					System.out.println(Thread.currentThread().getName()+"....."+x);
				}
			}
		}.start();
		


		for(int x=0; x<100; x++)
		{
			System.out.println(Thread.currentThread().getName()+"....."+x);
		}

		Runnable r  = new Runnable()
		{
			public void run()
			{
				for(int x=0; x<100; x++)
				{
					System.out.println(Thread.currentThread().getName()+"....."+x);
				}
			}
		};
		new Thread(r).start();


		//new Test1().start();
	}
}
/*
class Test1 extends Thread
{
	public void run()
	{
		for(int x=0; x<100; x++)
		{
			System.out.println(Thread.currentThread().getName()+"....."+x);
		}
	}
}
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值