一、多线程的概念:要理解多线程得先了解线程和进程的概念。进程是操作系统结构的基础;是一个正在执行的程序;计算机中正在运行的程序实例。它可能存在多条执行路径。而一个线程就是进程的一个执行路径。线程是进程中的内容,程序中的独立控制单元,每一个线程执行都有一个执行顺序。
二、多线程的好处:没有多线程就没有用户交互界面。当然,多线程也可能会提高程序的运行效率。我一个任务没有必要等待另一个任务的完成。多线程还有很多其他优点。
三、多线程的坏处:使用多线程虽然有很多好处,但是也有它的不好的地方。其中一个是,设计不好多线程可能就会发生死锁,或者集体等待。其他的坏处还有,线程太多,会影响性能;占用跟多的内存。
四、JAVA多线程的实现:在JAVA中有两种方法来实现多线程。一个是拓展Thread类,一个是实现Runnable接口。
拓展方法:1、继承Thread类 。
2、覆盖Thread类里面的run()方法。
3、创建并启动一个线程。启动用的是start()方法。线程启动后,JVM就会启动run()方法来执行线程。
示例:
public class NewThreadMethod1 {
public static void main(String[] args) {
NewThread newThread = new NewThread();
newThread.start();
new NewThread().start();
}
}
class NewThread extends Thread{
@Override
public void run() {
int i = 0;
while (i < 100) {
System.out.println(currentThread().getName() + " lailongwei");
i++;
}
}
}
这里解释下,run()方法是自定义代码的地方。线程运行的代码块。由JVM来调用。start方法是开启线程,并在线程中执行run()方法。
实现方法:1、定义类,实现接口。
2、覆盖Runnable接口中的run方法。
3、把这个类当作参数传递给Thread的构造函数,并启动线程。(new Thread(Runnable).start())。
示例:
public class NewThreadMethod2 {
public static void main(String[] args) {
new Thread(new NewRunnable()).start();
new Thread(new NewRunnable()).start();
}
}
class NewRunnable implements Runnable{
@Override
public void run() {
int i = 0;
while (i < 100) {
System.out.println(Thread.currentThread().getName() + " lailongwei");
i++;
}
}
}
五、拓展方法和实现方法的区别:1、JAVA中只能有一个extends,实现方法的好处,避免了单继承的局限性。在定义多线程时,建议使用实现方法。
2、Runnable任务可以被多线程同时使用。而拓展方法不可以。
3、线程代码存放的位置不一样。
六、线程的状态:
需要注意的阻塞状态和等待状态的区别,阻塞状态是等待CPU的执行权,具备运行资格。等待状态是放弃了执行资格。
七、线程的标识:线程可以通过setName方法活或者Thread(String name)方法来设置自己的表示名称。一般情况下,线程的标识是“Thread-编号”。可以通过getName,
Thread.currentThread().getName()方法来获取标识。
八、多线程的运行出现安全问题。
1、出现安全问题的原因是,当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程就参与进来。导致错误的发生。
示例如下:
public class ThreadError {
public static void main(String[] args) {
new Thread(new Count()).start();
new Thread(new Count()).start();
new Thread(new Count()).start();
}
}
class Count implements Runnable{
int count = 0;
@Override
public void run() {
for (int i = 0; i < 100; i++) {
count = i;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count--;
System.out.println(Thread.currentThread().getName() + "::" + count);
}
}
}
2、如何找多线程的安全问题:a,明确有哪些共享数据。b、明确哪些语句是操作共享数据的。
3、解决方法。有两种解决办法。一个是同步代码块。一个是编写同步函数。
同步代码块的
a、问题代码用同步代码块的解决:
public class ThreadError {
public static void main(String[] args) {
new Thread(new Count()).start();
new Thread(new Count()).start();
new Thread(new Count()).start();
}
}
class Count implements Runnable{
int count = 0;
@Override
public void run() {
synchronized (Runnable.class) {
for (int i = 0; i < 100; i++) {
count = i;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count--;
System.out.println(Thread.currentThread().getName() + "::" + count);
}
}
}
}
就是把需要同步的语句放到同步代码块中。这里用的锁是Runnable.class。 也就是synchronich()括号中的类。
b、用同步函数解决:
public class ThreadError {
public static void main(String[] args) {
new Thread(new Count()).start();
new Thread(new Count()).start();
new Thread(new Count()).start();
}
}
class Count implements Runnable{
int count = 0;
@Override
public void run() {
method2();
}
private synchronized void method2() {
for (int i = 0; i < 100; i++) {
count = i;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count--;
System.out.println(Thread.currentThread().getName() + "::" + count);
}
}
}
就是把需要同步的语句放到一个函数中,然后把这个函数定义成synchoronized。这里使用的锁是this。也就是调用这个函数的对象的引用。需要注意的是,在静态方法中,使用的锁是类名.class。
九、死锁。死锁发生的原因是循环等待。也就是同步中嵌套同步,但是锁却不同。
死锁的示例:
class Deadlocker {
int field_1;
private Object lock_1 = new int[1];
int field_2;
private Object lock_2 = new int[1];
public void method1(int value) {
“synchronized” (lock_1) {
“synchronized” (lock_2) {
field_1 = 0; field_2 = 0;
}
}
}
public void method2(int value) {
“synchronized” (lock_2) {
“synchronized” (lock_1) {
field_1 = 0; field_2 = 0;
}
}
}
}
----------------------- android培训、java培训、java学习型技术博客、期待与您交流! ----------------------
详情请查看: