1、idea的安装
尚硅谷_宋红康_IntelliJIDEA的安装、配置与使用.pdf
2、基本概念:程序、进程、线程
多线程程序的优点:
1. 提高应用程序的响应。对图形化界面更有意义,可增强用户体验。
2. 提高计算机系统CPU的利用率
3. 改善程序结构。将既长又复杂的进程分为多个线程,独立运行,利于理解和修改
何时需要多线程
程序需要同时执行两个或多个任务。
程序需要实现一些需要等待的任务时,如用户输入、文件读写操作、网络操作、搜索等。
需要一些后台运行的程序时。
3、线程的创建和使用
方式一:继承Thread类
1) 定义子类继承Thread类。
2) 子类中重写Thread类中的run方法。 将此线程执行的操作声明在run()中
3) 创建Thread子类对象,即创建了线程对象。
4) 调用线程对象start方法:①启动当前线程,②调用当前现成的run方法。
注意点:
1、我们不能通过直接调用run()的方式启动线程。
2、一个线程对象只能调用一次start()方法启动线程。
匿名子类调用start方法。
package com.atguigu.java2;
public class ThreadDemo {
public static void main(String[] args) {
/*MyThread1 myThread1 = new MyThread1();
MyThread2 myThread2 = new MyThread2();
myThread1.start();
myThread2.start();*/
new Thread() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}.start();
}
}
class MyThread1 extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}
class MyThread2 extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i % 2 != 0) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}
package com.atguigu.java2;
/*
测试Thread中的常用方法
1、start():启动当前线程;调用当前现成的run()
2、run();通常需要重写Thread中的此方法,将创建的线程要执行的操作声明在此方法中
3、currentThread():静态方法,返回执行当前代码的线程
4、getName():获取当前线程的名字
5、setName():设置当前线程的名字
6、yield():释放当前CPU的执行权,
7、join():在线程的a中调用的join(),此时线程a就进入阻塞状态,直到线程b完全执行完以后,线程a才结束阻塞状态
8、stop():已过时,当执行此方法时,强制结束当前线程
9、sleep(long millis):让当前线程睡眠指定的毫秒数。在指定的时间内,当前的线程是阻塞状态
10、isAlive():判断当前对象是否存活。
*/
public class ThreadMethodTest {
public static void main(String[] args) {
HelloThread h1 = new HelloThread("Thread:1");
//h1.setName("线程一");
h1.start();
//给主线程命名
Thread.currentThread().setName("主线程");
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
if (i==20){
try {
h1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println(h1.isAlive());
}
}
class HelloThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
try {
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + i);
}
/* if (i % 20 == 0) {
yield();
}*/
}
}
public HelloThread(String name) {
super(name);
}
}
package com.atguigu.java2;
/*
例子:创建三个c窗口买票,总票数为100章
存在线程安全
*/
class Windows extends Thread{
private static int ticket=100;
@Override
public void run() {
while (true){
if (ticket>0){
System.out.println(getName()+":卖票,票号为:"+ticket);
ticket--;
}else{
break;
}
}
}
}
public class WindowsTest {
public static void main(String[] args) {
Windows t1 = new Windows();
Windows t2 = new Windows();
Windows t3 = new Windows();
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t1.start();
t2.start();
t3.start();
}
}
方式二:实现Runnable接口
1) 定义子类,实现Runnable接口。
2) 子类中重写Runnable接口中的run方法。
3) 通过Thread类含参构造器创建线程对象。
4) 将Runnable接口的子类对象作为实际参数传递给Thread类的构造器中。
5) 调用Thread类的start方法:开启线程,调用Runnable子类接口的run方法。
package com.atguigu.java2;
class MThread implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i%2==0){
System.out.println(Thread.currentThread.getName()+":"+i);
}
}
}
}
public class ThreadTest1 {
public static void main(String[] args) {
MThread mThread = new MThread();
Thread t1 = new Thread(mThread);
t1.setName("线程一");
t1.start();
Thread t2 = new Thread(mThread);
t2.setName("线程二");
t2.start();
}
}
package com.atguigu.java2;
//存在线程安全
class Window1 implements Runnable {
private int ticket = 100;
@Override
public void run() {
while (true) {
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + ":卖票,票号为:" + ticket);
ticket--;
} else {
break;
}
}
}
}
public class WindowsTest1 {
public static void main(String[] args) {
Window1 w = new Window1();
Thread t1 = new Thread(w);
Thread t2 = new Thread(w);
Thread t3 = new Thread(w);
t1.setName("窗口一");
t2.setName("窗口二");
t3.setName("窗口三");
t1.start();
t2.start();
t3.start();
}
}
比较创建线程的两种方式:
开发中:优先选择:实现Runnable接口的方式
原因:1、实现的方式没有类的单继承性的局限性
2、实现的方式更适合来处理多个线程有共享的情况
相同点:两种方式都需要重写run(),将线程要执行的逻辑声明在run().