1.创建线程
首先讲一下Thread的构造器
方式一:继承Thread类
1.继承Thread类 2.重写run方法 3.创建对象 4.调用start方法
//两个线程输出1-100之间奇偶数
//线程一:输出奇数
class MyThread1 extends Thread{ //1.继承Thread
@Override
public void run() { //2.重写run方法
for (int i = 0; i < 100; i++) {
if (i%2!=0){
System.out.println(i+"线程1");
}
}
}
}
//线程2:输出偶数
class MyThread2 extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i%2==0){
System.out.println(i+":线程2");
}
}
}
}
//主线程
public class MyThread {
public static void main(String[] args) {
MyThread1 mth1 = new MyThread1(); //3.创建对象
MyThread2 mth2 = new MyThread2();
mth1.start(); //4.调用.start方法
mth2.start();
}
}
方式二:实现Runnable接口
1.实现Runnable接口 2.重写run方法 3.通过Thread类的构造器创建对象 4.将含Runnable接口的对象作为参数传给Thread类构造器中 5.调用Thread类的start方法
//通过Runnable接口实现多线程
class Runnable1 implements Runnable{ //1.实现Runnable接口
private String name;
public Runnable1(String name) {
this.name = name;
}
@Override
public void run() { //2.重写run方法
for (int i = 0; i < 5; i++) {
System.out.println(name +":"+i);
try {
Thread.sleep((int) (Math.random()*10));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//main方法
public class MyRunnable{
public static void main(String[] args) {
Runnable1 run1 = new Runnable1("A");
Runnable1 run2 = new Runnable1("B");
Thread aaa =new Thread(run1);
aaa.start();
new Thread(new Runnable1("c")).start();//3.new Thread类构造器 4.含Runnbale接口的对象作为参数传给Thread类构造器 5调用.start方法
}
}
Runnable和Thread实现多线程的区别:
1.Runnable可以实现资源共享,创建一个Runnable接口的对象,这个对象作为一个参数传进Thread类里面两次,创建两个线程,但是两个线程执行的都是同一个任务,而Thread每创建一个类就是一个任务,不能实现资源共享
2.Thread是单继承,有局限性
方式三:实现callable接口
1.创建实现callable接口的实现类
2.重写call方法
3.创建接口实现类的对象
4.对象作为参数传给futuretask可以得到返回值,
5.futuretask作为参数传给线程类,完成线程的创建
/**
* @author zkx
* @create 2022-02-03 22:48
*/
public class CallableTest {
public static void main(String[] args) {
//3.创建实现callable接口的实现类的对象
Numbe nn = new Numbe();
//4.将对象作为参数传给FutureTask, FutureTask可以得到callable的返回值
FutureTask futureTask = new FutureTask(nn);
//5.将futureTask对象作为参数传给线程类,实现线程的创建
Thread t = new Thread(futureTask);
t.start();
//利用futureTask得到callable的返回值
try {
Object num = futureTask.get();
System.out.println("总和为:"+num);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
//1.创建实现callable接口的实现类
class Numbe implements Callable{
private int num;
//2.重写call方法
@Override
public Object call() throws Exception {
for (int i = 1; i <= 100; i++) {
if(i%2==0) {
System.out.println(i);
num += i;
}
}
return num;
}
}
ExecutorService executorService = Executors.newFixedThreadPool(10);
2.执行线程
executorService.execute(number1);//execute适用于Runnable接口
executorService.submit();//submit适用于callable接口
3.关闭线程池
executorService.shutdown();
public class ExecutorsTest {
public static void main(String[] args) {
//1。首先创建一个线程池,里面有十个可用线程,ExecutorService是接口继承于Executors是工具类
ExecutorService executorService = Executors.newFixedThreadPool(10);
//ThreadPoolExecutor是ExecutorService的一个子类
ThreadPoolExecutor service = (ThreadPoolExecutor) executorService;
service.setCorePoolSize(15);
service.setMaximumPoolSize(10);
// service.setKeepAliveTime(l);
Number1 number1 =new Number1();
Number2 number2 =new Number2();
//2.执行线程,但是线程执行的方法需要自己写
executorService.execute(number1);//execute适用于Runnable接口
executorService.execute(number2);
// executorService.submit();//submit适用于callable接口
//3.关闭连接池
executorService.shutdown();
}
}
class Number1 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i%2==0){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
}
class Number2 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i%2!=0){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
}
2.同步问题
解决同步的方法:
1.同步代码块
synchronized(同步监视器){
需要被同步的代码
}
//例子:创建个窗口卖票,总票数为100张.使用实现Runnable接口的方式
//main方法
public class SaleTicket {
public static void main(String[] args) {
Ticket t1 = new Ticket();
Thread thr1 =new Thread(t1);
Thread thr2 = new Thread(t1);
thr1.setName("A");
thr2.setName("B");
thr1.start();
thr2.start();
}
}
class Ticket implements Runnable{
private static int TICKET_NUM =100;//总票数为100
@Override
public void run() {
while (true){
synchronized (this){//如果是继承的话,就不能用this,需要用Ticket.class
if (TICKET_NUM>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"窗口:售票,票号为"+TICKET_NUM);
TICKET_NUM--;
}
else {
break;
}
}
}
}
}
2.同步方法
public synchronized void 同步方法(){
需要被同步的代码
}
//例子:创建个窗口卖票,总票数为100张.使用实现Runnable接口的方式
//main方法
public class SaleTicket {
public static void main(String[] args) {
Ticket t1 = new Ticket();
Thread thr1 =new Thread(t1);
Thread thr2 = new Thread(t1);
thr1.setName("A");
thr2.setName("B");
thr1.start();
thr2.start();
}
}
class Ticket implements Runnable{
private static int TICKET_NUM =100;//总票数为100
@Override
public void run() {
while (true){
show();//同步方法
}
}
//同步方法
public synchronized void show(){//这是接口实现同步的方法,如果是继承的话,需要static静态的
if (TICKET_NUM>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"窗口:售票,票号为"+TICKET_NUM);
TICKET_NUM--;
}
}
}
3.lock锁
1.创建锁 ReentrantLock lock = new ReentrantLock()
try{
2.使用锁 lock.lock()
}finally{
3.解锁 lock.unlock()
}
//例子:创建个窗口卖票,总票数为100张.使用实现Runnable接口的方式
//main方法
public class SaleTicket {
public static void main(String[] args) {
Ticket t1 = new Ticket();
Thread thr1 =new Thread(t1);
Thread thr2 = new Thread(t1);
thr1.setName("A");
thr2.setName("B");
thr1.start();
thr2.start();
}
}
class Ticket implements Runnable{
private static int TICKET_NUM =100;//总票数为100
private ReentrantLock lock = new ReentrantLock(); //创建lock锁
@Override
public void run() {
while (true){
try{
lock.lock(); //使用lock锁方法
if (TICKET_NUM>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"窗口:售票,票号为"+TICKET_NUM);
TICKET_NUM--;
}else{
break;
}
}finally{
lock.unlock(); //解锁
}
}
}
}
3.线程通信
wait() 阻塞当前线程,并释放锁
notify()唤醒一个阻塞的线程
notifyall()唤醒所有阻塞的线程
以上三个方法的调用者必须是 同步监视器
/**线程通信
*
*
* @author zkx
* @create 2022-02-03 22:20
*/
//使用两个线程打印 1-100。线程1, 线程2 交替打印
public class CommunicationTest {
public static void main(String[] args) {
Number nb = new Number();
Thread t1 = new Thread(nb);
Thread t2 =new Thread(nb);
t1.setName("线程A");
t2.setName("线程B");
t1.start();
t2.start();
}
}
class Number implements Runnable{
private int num =1;
@Override
public void run() {
while (true){
synchronized (this){
notify();//没有阻塞的线程拿到锁之后,唤醒阻塞的线程
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (num<=100){
System.out.println(Thread.currentThread().getName()+":"+num);
num++;
try {
wait();//打印完了,当前线程阻塞,并释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
break;
}
}
}
}
}

被折叠的 条评论
为什么被折叠?



