一.在java中要想实现多线程,有两种方法,一种是继续Thread类,另外一种是实现Runable接口。
对于直接继承Thread的类来说,下面是一个简单的例子:
1.FirstThread继承Thread类
class FirstThread extends Thread{
public void run() {
for(int i = 0;i<100;i++){
System.out.println("FirstThread-->"+i);
}
}
}
public class Test {
public static void main(String[] args) {
//生成线程类的对象
//FirstThread ft = new FirstThread();
//启动线程
//ft.start();
}
}
对于直接继承Thread的类来说,下面是一个简单的例子:
1.RunableIml实现Runable接口
import java.io.EOFException;
public class RunnableIml implements Runnable{
private int i;
public void run() {
for(int i = 0;i<100;i++){
System.out.println("Runnablle-->"+i);
}
if( i == 50) {
try{
Thread.sleep(60000);
}catch(Exception e){
System.out.println(e);
}
}
}
}
2.主方法
public class Test {
public static void main(String[] args) {
//生成一个Runnable的接口实现类的对象
RunnableIml iml = new RunnableIml();
//生成Thread的对象,并将生成的Runnable对象传进来。
Thread i = new Thread(iml);
//启动Thread对象,调用start的方法
i.start();
/*for(int i=0;i<100;i++){
System.out.println("main-->"+i);
}*/
//ft.run();不能这样写。。。
}
}
二.java中的
线程池
下面看看TheadPool常用的方法
1:GetMaxThreads,GetMinThreads
class Program
{
static void Main(string[] args)
{
int workerThreads;
int completePortsThreads;
ThreadPool.GetMaxThreads(out workerThreads, out completePortsThreads);
Console.WriteLine("线程池中最大的线程数{0},线程池中异步IO线程的最大数目{1}", workerThreads, completePortsThreads);
ThreadPool.GetMinThreads(out workerThreads, out completePortsThreads);
Console.WriteLine("线程池中最小的线程数{0},线程池中异步IO线程的最小数目{1}", workerThreads, completePortsThreads);
}
}
①:线程很多的话,线程调度就越频繁,可能就会出现某个任务执行的时间比线程调度花费的时间短很多的问题。
②:同时一个线程默认占用1M的堆栈空间。
2:SetMaxTheads,SetMinThreads
class Program
{
static void Main(string[] args)
{
int workerThreads;
int completePortsThreads;
ThreadPool.SetMaxThreads(100, 50);
ThreadPool.SetMinThreads(20, 10);
ThreadPool.GetMaxThreads(out workerThreads, out completePortsThreads);
Console.WriteLine("线程池中最大的线程数{0},线程池中异步IO线程的最大数目{1}\n", workerThreads, completePortsThreads);
ThreadPool.GetMinThreads(out workerThreads, out completePortsThreads);
Console.WriteLine("线程池中最小的线程数{0},线程池中异步IO线程的最小数目{1}\n", workerThreads, completePortsThreads);
}
}
3: QueueUserWorkItem
需要容纳任务并执行的方法来了,该方法有一个WaitCallBack的委托,我们只需要把将要执行的任务丢给委托,CLR将会在线程池中调派空闲的
线程执行。
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
ThreadPool.QueueUserWorkItem(Run1);
Console.Read();
}
static void Run1(object obj)
{
Console.WriteLine("我是线程{0},我是线程池中的线程吗? \n回答:{1}", Thread.CurrentThread.ManagedThreadId,
Thread.CurrentThread.IsThreadPoolThread);
}
}
}
可能我们也需要像普通的Thread一样带一些参数到工作线程中,QueueUserWorkItem的第二个重载版本解决了我们的问题。
class Program
{
static void Main(string[] args)
{
ThreadPool.QueueUserWorkItem(Run1, "我是主线程");
Console.Read();
}
static void Run1(object obj)
{
Console.WriteLine(obj);
}
}
4:RegisterWaitForSingleObject
我们知道,如果我们把要执行的任务丢给线程池后,相当于把自己的命运寄托在别人的手上。
①:我们再也不能控制线程的优先级了。
②:丢给线程池后,我们再也不能将要执行的任务取消了。
是的,给别人就要遵守别人的游戏规则,不过RegisterWaitForSingleObject提供了一些简单的线程间交互,因为该方法的第一个参数是
WaitHandle,在VS对象浏览器中,我们发现EventWaitHandle继承了WaitHandle,而ManualResetEvent和AutoResetEvent都继承于
EventWaitHandle,也就是说我们可以在RegisterWaitForSingleObject溶于信号量的概念。
class Program
{
static void Main(string[] args)
{
AutoResetEvent ar = new AutoResetEvent(false);
ThreadPool.RegisterWaitForSingleObject(ar, Run1, null, Timeout.Infinite, false);
Console.WriteLine("时间:{0} 工作线程请注意,您需要等待5s才能执行。\n", DateTime.Now);
//5s
Thread.Sleep(5000);
ar.Set();
Console.WriteLine("时间:{0} 工作线程已执行。\n", DateTime.Now);
Console.Read();
}
static void Run1(object obj, bool sign)
{
Console.WriteLine("当前时间:{0} 我是线程{1}\n", DateTime.Now, Thread.CurrentThread.ManagedThreadId);
}
}
在Threading下面有一个Timer计时器,当定期触发任务的时候都是由线程池提供并给予执行,那么这里我们溶于信号量的概念以后同样
可以实现计时器的功能。
class Program
{
static void Main(string[] args)
{
AutoResetEvent ar = new AutoResetEvent(false);
//参数2000:其实就是WaitOne(2000),采取超时机制
ThreadPool.RegisterWaitForSingleObject(ar, Run1, null, 2000, false);
Console.Read();
}
static void Run1(object obj, bool sign)
{
Console.WriteLine("当前时间:{0} 我是线程{1}\n", DateTime.Now, Thread.CurrentThread.ManagedThreadId);
}
}
}
RegisterWaitForSingleObject返回一个RegisteredWaitHandle类,那么我们就通过RegisteredWaitHandle来动态的控制。
class Program
{
static void Main(string[] args)
{
RegisteredWaitHandle handle = null;
AutoResetEvent ar = new AutoResetEvent(false);
handle = ThreadPool.RegisterWaitForSingleObject(ar, Run1, null, 2000, false);
//10s后停止
Thread.Sleep(10000);
handle.Unregister(ar);
Console.WriteLine("大哥,主线程要干掉我。");
Console.Read();
}
static void Run1(object obj, bool sign)
{
Console.WriteLine("当前时间:{0} 我是线程{1}", DateTime.Now, Thread.CurrentThread.ManagedThreadId);
}
}