java的多线程问题——2
线程中存在的一些现象
1.线程加入
public final void join()
等待该线程中止,其他线程才能继续抢着执行
首先创建一个线程类,然后在测试类中创建对象。
package com.wy.join;
public class MyThread extends Thread{
@Override
public void run() {
for (int j = 0; j < 100; j++) {
System.out.println(this.getName()+" "+ j);
}
}
}
线程加入是只有该线程运行完,其他线程才能继续运行。
package com.wy.join;
public class Test {
public static void main(String[] args) {
MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();
MyThread mt3 = new MyThread();
mt1.setName("one");
mt2.setName("two");
mt3.setName("three");
mt1.start();
try {
mt1.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mt2.start();
mt3.start();
}
}
2.线程礼让
public static void yield():
暂停当前正在执行的线程对象,并执行其他线程。
作用:让线程间的执行更和谐一些,但是实际上做不到。可以通过后面讲解的知识来实现。
package com.wy.yield;
import com.wy.join.MyThread;
public class YieldTest {
public static void main(String[] args) {
MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();
MyThread mt3 = new MyThread();
mt1.setName("one");
mt2.setName("two");
mt3.setName("three");
mt1.start();
Thread.yield();
mt2.start();
mt3.start();
}
}
3.线程死亡
public final void stop():直接杀死
public void interrupt():直接杀死,在死前,还可以有遗言。
创建线程类,线程方法中进行休眠。
package com.wy.stop;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MyThread extends Thread{
@Override
public void run() {
System.out.println(new SimpleDateFormat("HH:mm:ss").format(new Date()));
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
System.out.println("be killed");
}
System.out.println(new SimpleDateFormat("HH:mm:ss").format(new Date()));
}
}
package com.wy.stop;
public class StopTest {
public static void main(String[] args) {
MyThread mt = new MyThread();
mt.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//public final void stop():直接杀死
//mt.stop();
//public void interrupt():直接杀死,在死前,还可以有遗言。
mt.interrupt();
}
}
4.线程休眠
static void sleep(long millis) 线程睡一会
线程的生命周期
- 新建
- 就绪
- 运行
- 有可能阻塞
- 死亡
(引用)
线程之间通信
线程间通信(生产消费者问题):不同类型线程针对同一个资源的操作,会产生线程的通信问题。
线程组
Java中使用ThreadGroup来表示线程组,它可以对一批线程进行分类管理,Java允许程序直接对线程组进行控制。
下面的代码需要首先有个MyThread类,这里没有提供这个类,直接提供测试类。
package com.wy.threadgroup;
public class GroupTest {
public static void main(String[] args) {
MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();
Thread t1 = new Thread(mt1);
Thread t2 = new Thread(mt2);
ThreadGroup tg1 = t1.getThreadGroup();
ThreadGroup tg2 = t2.getThreadGroup();
System.out.println(tg1.getName());
System.out.println(tg2.getName());
System.out.println("-----------------");
ThreadGroup tg3 = new ThreadGroup("xcc");
System.out.println(tg3.getName());
}
}
线程池
程序启动一个新线程成本是比较高的,因为它涉及到要与操作系统进行交互。而使用线程池可以很好的提高性能,尤其是当程序中要创建大量生存期很短的线程时,更应该考虑使用线程池。
线程池的特点:
线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。
线程池的使用步骤
1.创建线程池对象
ExecutorService pool = Executors.newFixedThreadPool(2);
2.创建Runnable实例
MyRunnable my = new MyRunnable();
3.提交Runnable实例
pool.submit(my);
pool.submit(my);
4.关闭线程池
pool.shutdown();
线程池中的线程可以是实现Runnable接口的类,也可以是实现Callable接口的类
1.实现Runnable接口的线程池
package com.wy.runpool;
public class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println(Thread.currentThread().getName()+"+"+i);
}
}
}
下面是建立的实现Runnable接口的线程池。
package com.wy.runpool;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class RunTest {
public static void main(String[] args) {
//创建线程池对象
ExecutorService pool = Executors.newFixedThreadPool(2);
//创建Runnable实例
MyRunnable mr = new MyRunnable();
MyRunnable mr2 = new MyRunnable();
//提交Runnable实例
pool.submit(mr);
pool.submit(mr2);
pool.shutdown();
}
}
实现Callable接口的测试类:
package com.wy.callpool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CallTest {
public static void main(String[] args) {
//创建线程池对象
ExecutorService pool = Executors.newFixedThreadPool(2);
//创建实现Callable接口的对象
MyCallable mc = new MyCallable();
MyCallable mc2 = new MyCallable();
//提交Callable实例
pool.submit(mc);
pool.submit(mc2);
//关闭线程池
pool.shutdown();
}
}
定时器Timer
构造方法
public Timer()构造
public void schedule(TimerTask task, long delay)延迟多久执行任务
public void schedule(TimerTask task,long delay,long period)延迟多久执行任务,并以后每隔多久执行一次
1.需求:延迟10秒输出我爱中国
package com.wy.timer2;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
public static void main(String[] args) {
Timer t = new Timer();
t.schedule(new MyTimerTask(), 10000);
}
}
class MyTimerTask extends TimerTask{
@Override
public void run() {
System.out.println("我爱中国");
}
}
2.延时5秒输入I love xcc.每隔1秒也输出这句话。
首先建立Task
package com.wy.timer;
import java.util.TimerTask;
public class MyTimerTask extends TimerTask{
@Override
public void run() {
System.out.println("I love xcc.");
}
}
进行测试:
package com.wy.timer;
import java.util.Timer;
public class TimerTest {
public static void main(String[] args) {
Timer t = new Timer();
MyTimerTask mt = new MyTimerTask();
t.schedule(mt, 5000, 1000);
}
}