多线程实现

1.进程与线程的概念
java的第一大特色:多线程的编码支持。
进程:操作系统中一个程序的执行周期称为一个进程。
在DOS系统的时代,由于本身就是一个单进程的操作系统,所以在同一时间段上只能够有一个程序执行。后来发展到windows系统后,我们发现多个程序可以同时执行,所以windows是一个多进程的操作系统。

线程:一个程序同时执行多个任务。通常,每一个任务就称为一个线程。

与进程相比,线程更“轻量级”,创建,撤销一个线程要比启动一个新进程开销要小得多。没有进程就没有线程,进程一旦终止,其内的线程也将不复存在。

多进程与多线程的区别:本质区别在于,每一个进程拥有自己的一整套变量,而线程则共享数据。共享变量使得线程之间的通信比进程之间通信更有效更方便


多线程表现在哪里呢?

例如,一个浏览器应用可以同时下载多个图片,音乐;一个Web服务器需要同时处理多个并发的请求。这些都是多线程的应用。

高并发:访问的线程量非常非常高。造成服务器内存不够用,无法处理新的请求。



继承Thread实现多线程
java.lang.Thread是一个线程操作的核心类。新建一个线程最简单的方法就是直接继承Thread类,而后覆写该类中的run()方法(就相当于主类中的main方法)
正确启用多线程的方法是调用Thread类中的start()方法。
启动多线程: public synchronized void start() 此方法会自动调用线程的run()方法
每一个线程只能启动一次
start0()方法是一个只声明而未实现的的方法同时使用native关键字进行定义。
native指的是调用本机的原生系统函数。
Thread 类有个registerNatives本地方法,该方法主要作用就是注册一些本地方法供Thread类使用,如start0(),stop0()等等,可以说,所有操作本地线程的本地方法都是由它注册的。这个方法放在static语句块中,当该类被加载到JVM中的时候,它就会被调用,进而注册相应的本地方法。而本地方法registerNatives是定义在Thread.C文件中的。它定义了各个操作系统平台都要用到的关于线程的公用数据和操作。


class MyThread extends Thread {//线程主体类
private String title;
public MyThread(String title) {
this.title=title;
}
public void run() {//所有线程从此处开始执行
for(int i=0;i<10;i++) {
System.out.println(this.title+",i="+i);
}
}
}
public class Line {

public static void main(String[] args) {
MyThread myThread1=new MyThread("thread1");

MyThread myThread2=new MyThread("thread2");

MyThread myThread3=new MyThread("thread3");

myThread1.start();
myThread2.start();
myThread3.start();
  }

}


Runnable()接口实现多线程。

Thread类的核心功能是进行线程的启动。如果一个类为了实现多线程直接去继承Thread类就会有单继承局限。
利用Runnable接口实现线程主体类。
MyThread类继承的不再是Thread类而是Runnable接口,虽然解决了单继承局限问题,但是没有start()方法被继承了,而 Thread类提供的构造方法 public Thread(Runnable target)  可以接收Runnable接口对象。启动多线程。

多线程的启动永远都是Thread类的start()方法。

Runnable还有一个特点,使用Runnable实现的多线程的程序类可以更好的描述出程序共享的概念(并不是说Thread不能)

Runnable接口对象可以采用匿名内部类或者Lambda表达式来定义

class MyThread implements Runnable{
private String title;
public MyThread(String title) {
this.title=title;
}
public void run() {
for(int i=0;i<10;i++) {
System.out.println(this.title+",i="+i);
}
}
 } 
 public class Line{
public static void main(String[] args) {
MyThread myThread1=new MyThread("thread1");
MyThread myThread2=new MyThread("thread2");
MyThread myThread3=new MyThread("thread3");
new Thread(myThread1).start();
new Thread(myThread2).start();
new Thread(myThread3).start();

}

 }


Thread和Runnable的区别

1.Runnable类可以被多继承,而Thread只能单继承。

2.Thread类是Runnable接口的子类,Thread类覆写了Runnable接口的run()方法

@Override

public void run(){

if(target!=null){

target.run();

}

}


在多线程的处理上使用的就是代理设计模式(所有的真实业务操作都会有一个与之辅助的工具类或功能类共同完成)


Callable接口实现多线程

从JDK1.5开始追加了新的开发包:java.uti.concurrent。这个开发包主要是进行高并发编程使用,包含很多在高并发操作的类。在这个包里定义了一个新的接口Callable

Runnable中run()方法没有返回值,它的设计遵循了主方法的设计原则:线程开始了就别回头。但是很多时候需要一些返回值,例如某些线程执行完成后可能带来一些返回结果,这种情况下就只能利用Callable来实现多线程。

class MyThread implements Callable<String>{
private int ticket=10;
public String call()throws Exception{
while(this.ticket>0) {
System.out.println("票数剩余"+this.ticket--);
}
return "票卖完了,下次吧。。";
}
}
public class Line{
public static void main(String[] args)throws InterruptedException,ExecutionException {
FutureTask<String> task=new FutureTask<>(new MyThread());
new Thread(task).start();
new Thread(task).start();
System.out.println(task.get());

}

}


多线程的常用操作

多线程的运行状态是不确定的,所以对于多线程操作必须有一个明确标识出线程对象的信息,这个线程往往通过名称来描述。在Thread类中提供有如下的线程名称方法:

public Thread(Runnable target,String name)      构造  创建线程的时候设置名称

public final synchronized void setName(String name)  普通  设置线程名称

public final String getName()     普通   取得线程名称

要想取得线程的对象,在Thread类中提供有一个方法取得当前对象:

public static native Thread currentThread();

如果没有设置线程名,则会自动分配一个线程名称。需要注意的是,线程名字如果要设置请避免重复,同时中间不要修改。

主方法本身就是一个线程,所有的线程都是通过主线程创建并启动的



猜你喜欢

转载自blog.csdn.net/xjy22/article/details/80088189
今日推荐