1.线程概念,与进程的区别,
1.1、线程是程序在执行过程中能够执行程序中代码的执行单元;
1.2、线程有4种状态:运行,就绪,挂起和结束;
1.3、进程是指一段正在执行的程序;特别情况下,线程称为轻量级进程。线程为进程的最小执行单元。
一个进程包含多个线程,各个线程共享程序的内存空间(代码段,数据段和堆空间)和一些进程的资源(打开的文件),但是
各个线程有自己的栈空间。
为什么要使用多线程?
1.4、程序中都是以进程为单位,而每个进程包含多线程,线程之间以并发的方式执行着,使用多线程的原因是:
1)时间方面--可减少响应的时间,保证程序的良好交互性;
2)资源方面--与进程相比,线程的创建和切换开销更小,原因是在同一个进程中的线程能够共享代码段,数据段,
所以线程的启动和切换的开销比创建进程小多。同时,多线程在资源共享方面效率很高。
3)目前硬件上也具有多线程的能力,不合理使用计算机的资源会造成很大的浪费。
4)多线程能够简化程序的结构,使得程序便于理解。
2.同步和异步的区别
同步机制保证了资源的安全,存在多线程意味着在使用共享资源的时候有先后顺序,即为同步;
要实现同步操作,需要获得每一个线程对象的锁;从而保证只有一个线程能够进入互斥的代码块(临界区);
实现同步加“synchronized”关键字,但是会造成很大的系统开销!甚至会死锁。---同步控制不是越多越好。
实现同步的方式有两种:利用同步代码块和同步的方法。
每个线程都包含运行所需的数据或方法,为此,线程之间的运行互不相干。
当应用程序在对象上调用了一个需要花费较长时间来执行的方法,并且不希望让程序等待方法的返回值,就应
该使用异步的编程,异步能够提高程序的效率。
3.如何实现java多线程?
1)继承Thread类,重写run()方法(两个步骤)
Thread是Runnable接口的实例,是一个线程的实例。 启动一个线程的唯一方法是通过Thread类的start()方法,start()是一个native(本地)方法,它将启动一个线程并执行
run()方法(初始是空方法)。
注:调用start()方法并不是立即执行多线程代码,而是是的该线程进入一种可运行的状态,运行的时间由系统决定。
public class MyThread extends Thread{//创建线程类
public void run(){
System.out.println("MyThread");//线程的函数体
}
}
public class Test{
public static void main (String[] args){
MyThread mythread = new MyThread();
mythread.start();//开启线程
}
2)实现Runnable接口,重写run()方法(推荐使用)
1.自定义类实现Runnable,实现run()方法;
2.创建Thread对象,将Runnable接口的对象作为参数实例化Thread对象;
3.调用start()方法
public class MyThread2 implements Runnable{
public void run(){
System.out.println(MyThread2.run());
}
public class Test2{
public static void main (){
MyThread2 mythread = new MyThread2();
Thread t = new Thread(mythread);
t.start();
}
}
3)实现Callable,重写call()方法(不常见)
以上三种方法的前两种方法线程执行完没有返回值,只有最后一种带有返回值,当需要实现多线程时,
一般建议实现Runnable接口的方式。
因为:Thread类实现多种方法可以被派生类使用或重写,但是只有run()方法是必须要重写的,在run()方法中实现
这个线程的功能。
另外业内认为:一个类仅在需要被加强或者修改的时候需要被继承。
4.run()方法和start()方法的差别
1)系统通过调用线程类的start()方法来启动线程,表示线程处于就绪状态并不是运行状态,此时线程可被JVM来调度执行,
2)在执行过程中,JVM通过调用线程类的run()方法来进行实际的操作,当run()方法结束后即线程结束。
3)如果直接调用run()方法则会被当做是一个普通的函数调用,程序中仍只有主线程。
也就是说start()方法能够异步调用run()方法,但是直接调用run()方法,却是同步的,并不能达到多线程的目的;
4)只有通过调用start()方法才能够实现多线程的目的;
public class ThreadDemo extends Thread{
@Override
public void run() {
System.out.println("ThreadDemo.begin");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ThreadDemo.end");
}
}
public class ThreadDemoTest1 {
public static void DemoTest1() {
System.out.println("DemoTest1.begin");
Thread t1 = new ThreadDemo();
t1.start();
System.out.println("DemoTest1.end");
}
public static void DemoTest2() {
System.out.println("DemoTest2.begin");
Thread t1 = new ThreadDemo();
t1.run();
System.out.println("DemoTest2.end");
}
public static void main(String[] args) {
DemoTest1();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
DemoTest2();
}
}
运行结果为:
DemoTest1.begin
DemoTest1.end
ThreadDemo.begin
ThreadDemo.end
DemoTest2.begin
ThreadDemo.begin
ThreadDemo.end
DemoTest2.end
从结果运行得知:start()方法是异步的,调用run()方法是同步的;
5、多线程实现同步的方法有哪些?
java提供3种实现同步机制的方法
1.synchronized
1.1 synchronized方法
public synchronized void thread();
1.2 synchronized块
synchronized(object){}
2.wait() notify()方法
wait()方法的调用来释放对象锁(java中,每个对象都有一个对象锁与之相关联),进入等待状态
同时调用notify()方法或者notifyAll()通知其他正在等待的线程。并允许他们获得锁。notify()
是允许第一个,notifyAll()则通知其竞争。
3.Lock
6.sleep()方法和wait()方法有什么区别
原理不同:
sleep()方法是Thread类的静态方法,是线程控制自身流程。
wait()方法是object类的方法,用于线程间的通信,会使目前拥有该对象锁的进程等待。
对锁的处理机制不同:
sleep()方法让线程暂停执行一段时间,时间到就会自动恢复,不涉及线程之间的通信,不会释放锁。
wait()方法会释放锁。
使用的区域不同:
sleep()方法可以用在任意地方。要捕获异常,
wait()方法使用在同步控制方法或者同步代码块中,不需要捕获异常。
不会释放锁,可能造成死锁问题,推荐使用wait()方法
拓展:sleep()和yield()方法的区别:
sleep()不考虑优先级,yield()考虑优先级。
sleep()方法会阻塞状态,yield()方法会使得线程重新回到可执行的状态
sleep()有异常,yield没有异常;
1.1、线程是程序在执行过程中能够执行程序中代码的执行单元;
1.2、线程有4种状态:运行,就绪,挂起和结束;
1.3、进程是指一段正在执行的程序;特别情况下,线程称为轻量级进程。线程为进程的最小执行单元。
一个进程包含多个线程,各个线程共享程序的内存空间(代码段,数据段和堆空间)和一些进程的资源(打开的文件),但是
各个线程有自己的栈空间。
为什么要使用多线程?
1.4、程序中都是以进程为单位,而每个进程包含多线程,线程之间以并发的方式执行着,使用多线程的原因是:
1)时间方面--可减少响应的时间,保证程序的良好交互性;
2)资源方面--与进程相比,线程的创建和切换开销更小,原因是在同一个进程中的线程能够共享代码段,数据段,
所以线程的启动和切换的开销比创建进程小多。同时,多线程在资源共享方面效率很高。
3)目前硬件上也具有多线程的能力,不合理使用计算机的资源会造成很大的浪费。
4)多线程能够简化程序的结构,使得程序便于理解。
2.同步和异步的区别
同步机制保证了资源的安全,存在多线程意味着在使用共享资源的时候有先后顺序,即为同步;
要实现同步操作,需要获得每一个线程对象的锁;从而保证只有一个线程能够进入互斥的代码块(临界区);
实现同步加“synchronized”关键字,但是会造成很大的系统开销!甚至会死锁。---同步控制不是越多越好。
实现同步的方式有两种:利用同步代码块和同步的方法。
每个线程都包含运行所需的数据或方法,为此,线程之间的运行互不相干。
当应用程序在对象上调用了一个需要花费较长时间来执行的方法,并且不希望让程序等待方法的返回值,就应
该使用异步的编程,异步能够提高程序的效率。
3.如何实现java多线程?
1)继承Thread类,重写run()方法(两个步骤)
Thread是Runnable接口的实例,是一个线程的实例。 启动一个线程的唯一方法是通过Thread类的start()方法,start()是一个native(本地)方法,它将启动一个线程并执行
run()方法(初始是空方法)。
注:调用start()方法并不是立即执行多线程代码,而是是的该线程进入一种可运行的状态,运行的时间由系统决定。
public class MyThread extends Thread{//创建线程类
public void run(){
System.out.println("MyThread");//线程的函数体
}
}
public class Test{
public static void main (String[] args){
MyThread mythread = new MyThread();
mythread.start();//开启线程
}
2)实现Runnable接口,重写run()方法(推荐使用)
1.自定义类实现Runnable,实现run()方法;
2.创建Thread对象,将Runnable接口的对象作为参数实例化Thread对象;
3.调用start()方法
public class MyThread2 implements Runnable{
public void run(){
System.out.println(MyThread2.run());
}
public class Test2{
public static void main (){
MyThread2 mythread = new MyThread2();
Thread t = new Thread(mythread);
t.start();
}
}
3)实现Callable,重写call()方法(不常见)
以上三种方法的前两种方法线程执行完没有返回值,只有最后一种带有返回值,当需要实现多线程时,
一般建议实现Runnable接口的方式。
因为:Thread类实现多种方法可以被派生类使用或重写,但是只有run()方法是必须要重写的,在run()方法中实现
这个线程的功能。
另外业内认为:一个类仅在需要被加强或者修改的时候需要被继承。
4.run()方法和start()方法的差别
1)系统通过调用线程类的start()方法来启动线程,表示线程处于就绪状态并不是运行状态,此时线程可被JVM来调度执行,
2)在执行过程中,JVM通过调用线程类的run()方法来进行实际的操作,当run()方法结束后即线程结束。
3)如果直接调用run()方法则会被当做是一个普通的函数调用,程序中仍只有主线程。
也就是说start()方法能够异步调用run()方法,但是直接调用run()方法,却是同步的,并不能达到多线程的目的;
4)只有通过调用start()方法才能够实现多线程的目的;
public class ThreadDemo extends Thread{
@Override
public void run() {
System.out.println("ThreadDemo.begin");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ThreadDemo.end");
}
}
public class ThreadDemoTest1 {
public static void DemoTest1() {
System.out.println("DemoTest1.begin");
Thread t1 = new ThreadDemo();
t1.start();
System.out.println("DemoTest1.end");
}
public static void DemoTest2() {
System.out.println("DemoTest2.begin");
Thread t1 = new ThreadDemo();
t1.run();
System.out.println("DemoTest2.end");
}
public static void main(String[] args) {
DemoTest1();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
DemoTest2();
}
}
运行结果为:
DemoTest1.begin
DemoTest1.end
ThreadDemo.begin
ThreadDemo.end
DemoTest2.begin
ThreadDemo.begin
ThreadDemo.end
DemoTest2.end
从结果运行得知:start()方法是异步的,调用run()方法是同步的;
5、多线程实现同步的方法有哪些?
java提供3种实现同步机制的方法
1.synchronized
1.1 synchronized方法
public synchronized void thread();
1.2 synchronized块
synchronized(object){}
2.wait() notify()方法
wait()方法的调用来释放对象锁(java中,每个对象都有一个对象锁与之相关联),进入等待状态
同时调用notify()方法或者notifyAll()通知其他正在等待的线程。并允许他们获得锁。notify()
是允许第一个,notifyAll()则通知其竞争。
3.Lock
6.sleep()方法和wait()方法有什么区别
原理不同:
sleep()方法是Thread类的静态方法,是线程控制自身流程。
wait()方法是object类的方法,用于线程间的通信,会使目前拥有该对象锁的进程等待。
对锁的处理机制不同:
sleep()方法让线程暂停执行一段时间,时间到就会自动恢复,不涉及线程之间的通信,不会释放锁。
wait()方法会释放锁。
使用的区域不同:
sleep()方法可以用在任意地方。要捕获异常,
wait()方法使用在同步控制方法或者同步代码块中,不需要捕获异常。
不会释放锁,可能造成死锁问题,推荐使用wait()方法
拓展:sleep()和yield()方法的区别:
sleep()不考虑优先级,yield()考虑优先级。
sleep()方法会阻塞状态,yield()方法会使得线程重新回到可执行的状态
sleep()有异常,yield没有异常;